We’re excited to announce that OData Model Builder 3.0.0 Preview 1 has been officially released and is available on NuGet:
This is a major release that brings the library up to date with the latest .NET and OData ecosystem, featuring .NET 10 support, OData Library 9.x compatibility, and modernized date/time handling using native .NET types.
What’s New in OData Model Builder 3.0.0 Preview 1
Framework & Dependency Updates
.NET 10 Support
OData Model Builder now targets .NET 10, aligning with the latest .NET runtime and taking advantage of modern performance improvements and language features. The library has moved from net8.0 to net10.0 as its target framework.
OData Library 9.x Integration
This release updates all OData dependencies from version 8.0.x to 9.0.0-preview.3, ensuring full compatibility with the latest OData .NET (ODL) ecosystem:
- Microsoft.OData.Edm:
8.0.1→9.0.0-preview.3 - Microsoft.Spatial:
8.0.1→9.0.0-preview.3
The integration includes adapting to OData Library 9.x API changes, such as the removal of the CsdlTarget parameter from CSDL writer methods. This simplifies CSDL generation and aligns with OData Library’s focus on OData CSDL exclusively (Entity Framework CSDL is no longer supported in the modern .NET Core/EF Core ecosystem).
Breaking Changes: Modernized Date and Time Handling
Use System.DateOnly and System.TimeOnly
The most significant change in this release is the complete migration from legacy EDM date/time types to .NET’s native date and time types. This brings OData Model Builder in line with modern .NET standards and improves consistency across the framework.
What’s Changed:
- Removed: Support for
Microsoft.OData.Edm.DateandMicrosoft.OData.Edm.TimeOfDay - Added: Full support for
System.DateOnlyandSystem.TimeOnly
Specific Changes:
- Type Mappings Removed from
EdmLibHelpers:
// Removed:
typeof(Date) → EdmPrimitiveTypeKind.Date
typeof(TimeOfDay) → EdmPrimitiveTypeKind.TimeOfDay
// Now using native .NET types:
typeof(DateOnly) → EdmPrimitiveTypeKind.Date
typeof(TimeOnly) → EdmPrimitiveTypeKind.TimeOfDay
- Property Configuration Methods Removed from
StructuralTypeConfiguration<T>:Property()overloads forTimeOfDayandDatetypes are no longer available- Use the standard
Property()method withDateOnlyandTimeOnlyinstead
Migration Guidance
If you’re upgrading from OData Model Builder 2.x, you’ll need to update your code:
Before (2.x):
using Microsoft.OData.Edm;
public class Event
{
public Date EventDate { get; set; }
public TimeOfDay StartTime { get; set; }
}
After (3.0):
public class Event
{
public DateOnly EventDate { get; set; }
public TimeOnly StartTime { get; set; }
}
Configuration Updates:
All model configurations using Date or TimeOfDay properties need to be updated to use DateOnly and TimeOnly. The API surface is otherwise identical.
New Features
Enhanced TimeOnly Support
To provide feature parity with existing date/time handling, we’ve added new extension methods and helpers:
AsTimeOnly()Extension Method forPrimitivePropertyConfiguration:- Complements the existing
AsTimeOfDay()method - Provides explicit configuration for
TimeOnlyproperties - Used internally by conventions like
ColumnAttributeEdmPropertyConvention
- Complements the existing
IsTimeOnly()Helper Method inTypeHelper:- Enables type detection for
TimeOnlyproperties - Matches the pattern of existing type helpers like
IsDateOnly(),IsDateTime(), etc.
- Enables type detection for
Example Usage:
var builder = new ODataConventionModelBuilder();
builder.EntityType<Event>()
.Property(e => e.StartTime)
.AsTimeOnly();
Why These Changes Matter
Alignment with Modern .NET
By adopting DateOnly and TimeOnly, OData Model Builder leverages types that are:
- Native to .NET: No need for custom EDM-specific types
- Well-documented: Full framework support and documentation
- Consistent: Same types used across .NET applications
- Performant: Optimized by the .NET runtime
OData Spec Compliance
DateOnly and TimeOnly naturally align with the OData specification’s dateValue and timeOfDayValue requirements, ensuring protocol compliance:
Ecosystem Integration
This release ensures OData Model Builder works seamlessly with:
- OData Library 9.x: Full compatibility with the latest OData .NET stack
- .NET 10: Access to the latest runtime improvements and features
Summary
OData Model Builder 3.0.0 Preview 1 represents a significant step forward for the library:
- Modern .NET alignment: Full .NET 10 support with native
DateOnly/TimeOnlytypes - Breaking changes for long-term benefit: Removal of legacy EDM date/time types simplifies the API and improves maintainability
- OData 9.x compatibility: Seamless integration with the latest OData ecosystem
Getting Started
Install the preview package from NuGet:
dotnet add package Microsoft.OData.ModelBuilder --version 3.0.0-preview.1
Or add it directly to your .csproj file:
<PackageReference Include="Microsoft.OData.ModelBuilder" Version="3.0.0-preview.1" />
Quick Start Example
Here’s a complete example showing how to use the new DateOnly and TimeOnly types:
Step 1: Define your entity model
public class Event
{
public int Id { get; set; }
public string Title { get; set; }
public DateOnly EventDate { get; set; }
public TimeOnly StartTime { get; set; }
public TimeOnly EndTime { get; set; }
public string Location { get; set; }
}
Step 2: Build the OData model
using Microsoft.OData.ModelBuilder;
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Event>("Events");
var model = builder.GetEdmModel();
Step 3: View the generated CSDL
The model builder will generate CSDL that properly maps DateOnly to Edm.Date and TimeOnly to Edm.TimeOfDay:
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:DataServices>
<Schema Namespace="Default" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<EntityType Name="Event">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<Property Name="Title" Type="Edm.String" />
<Property Name="EventDate" Type="Edm.Date" Nullable="false" />
<Property Name="StartTime" Type="Edm.TimeOfDay" Nullable="false" />
<Property Name="EndTime" Type="Edm.TimeOfDay" Nullable="false" />
</EntityType>
<EntityContainer Name="Container">
<EntitySet Name="Events" EntityType="Default.Event" />
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
Complete working example:
using Microsoft.OData.ModelBuilder;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Csdl;
using System.Xml;
// Define the entity
public class Event
{
public int Id { get; set; }
public string Title { get; set; }
public DateOnly EventDate { get; set; }
public TimeOnly StartTime { get; set; }
public TimeOnly EndTime { get; set; }
}
// Build the model
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Event>("Events");
IEdmModel model = builder.GetEdmModel();
// Write out the CSDL
using var sw = new StringWriter();
using var xw = XmlWriter.Create(sw, new XmlWriterSettings { Indent = true });
CsdlWriter.TryWriteCsdl(model, xw, out var errors);
xw.Flush();
Console.WriteLine(sw.ToString());
This example demonstrates the seamless integration of .NET’s native date and time types with OData’s EDM model, making it easier than ever to build type-safe OData services.
Feedback
This is a preview release, and we welcome your feedback! Please try the package and share your experiences on the GitHub repository.
As we work toward the final 3.0.0 release, your input will help us ensure a smooth transition for the OData Model Builder community.
0 comments
Be the first to start the discussion.