.NET 11 Preview 5 includes new EF Core features and improvements:
dotnet efsupports file-based apps- Configuration file support for
dotnet ef - EF1004 warns when async EF queries run synchronously
- SQL Server 2022 compatibility is now the default
- Temporal period properties can map to CLR properties
- Generated C# uses file-scoped namespaces
- Query translation produces cleaner SQL
- Breaking changes
- Bug fixes
- Community contributors
All EF Core updates in .NET 11:
dotnet ef can now target C# file-based apps, so migration and scaffolding
commands can work with the single-file app model introduced for .NET 10
(dotnet/efcore #38157,
dotnet/efcore #38186). Use
--file for the target app and --startup-file when the design-time startup
file is different. Existing --project and --startup-project workflows keep
working for SDK-style projects.
dotnet ef migrations add InitialCreate --file .\App.cs
dotnet ef dbcontext scaffold \
"Data Source=app.db" \
Microsoft.EntityFrameworkCore.Sqlite \
--file .\Model.cs \
--startup-file .\App.csPreview 5 also improves dotnet ef diagnostics for file-based apps and project
metadata failures (dotnet/efcore #38190).
When metadata build output includes the root MSBuild or SDK error, dotnet ef
now surfaces that error instead of replacing it with a generic project-metadata
message.
dotnet ef now supports loading default options from a
.config/dotnet-ef.json file. This makes repeated commands simpler by letting
you set values such as project and startup project once and override them on
the command line only when needed. See
dotnet/efcore #37966.
The EF Core analyzer package adds EF1004 for calls to
System.Linq.AsyncEnumerable.ToAsyncEnumerable() on IQueryable<T>
(dotnet/efcore #38218). That
extension wraps synchronous enumeration in an IAsyncEnumerable<T>. For EF Core
queries, use AsAsyncEnumerable() so the database query runs through EF Core's
async query pipeline.
// EF1004: this can evaluate the EF query synchronously.
await foreach (var blog in blogsQuery.ToAsyncEnumerable())
{
Console.WriteLine(blog.Name);
}
// Use EF Core's async query pipeline instead.
await foreach (var blog in blogsQuery.AsAsyncEnumerable())
{
Console.WriteLine(blog.Name);
}Thank you @m-x-shokhzod for this contribution!
The SQL Server provider now uses compatibility level 160, SQL Server 2022, by default (dotnet/efcore #38199). This lets new EF Core applications use translations that depend on SQL Server 2022 syntax without opting in. Applications that target older SQL Server compatibility levels can continue to set the level explicitly.
optionsBuilder.UseSqlServer(
connectionString,
sqlServerOptions => sqlServerOptions.UseCompatibilityLevel(150));SQL Server temporal period columns can now map to regular CLR properties
instead of requiring shadow properties
(dotnet/efcore #38110). This
allows direct use of period values in queries and projections without
EF.Property(...).
EF Core's generated C# now uses file-scoped namespace declarations (dotnet/efcore #38256). The change applies to generated migrations, model snapshots, compiled models, and reverse-engineered code. It removes one indentation level from generated files and aligns EF Core output with modern C# project templates.
namespace MyApp.Migrations;
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
// ...
}
}EF Core removes redundant SQL casts that come from value-converted CLR types
with implicit conversions to their provider type
(dotnet/efcore #38156). For
example, a predicate over a value-converted string property now avoids wrapping
the column in a no-op CAST, which keeps the generated SQL simpler.
var users = await context.Users
.Where(u => EF.Functions.Like(u.Name, "Name%"))
.ToListAsync();SELECT [u].[Id], [u].[Name]
FROM [Users] AS [u]
WHERE [u].[Name] LIKE N'Name%'SQL Server and SQLite also translate Any() over byte[] properties
(dotnet/efcore #38168). SQL
Server translates to DATALENGTH([b].[Bytes]) > 0, and SQLite translates to
length("b"."Bytes") > 0.
var withPayload = await context.Documents
.Where(d => d.Payload.Any())
.ToListAsync();- Pre-.NET 11 obsolete APIs were removed. EF Core 11 removes APIs that were marked obsolete before EF Core 11 (dotnet/efcore #38145). Move to the replacement APIs before upgrading.
- Cosmos
idescaping changed. When EF Core generates Cosmosidvalues from composite keys, illegal characters are no longer escaped (dotnet/efcore #38244). Review this change before upgrading if your existing data depends on escaped IDs.
- Database initialization and migrations
EnsureCreated,EnsureCreatedAsync,Migrate, andMigrateAsyncnow use an execution strategy to retry on transient failures (dotnet/efcore #38274).
dotnet efdotnet ef migrations bundle --configuration <Name>now forwards custom configuration names instead of onlyDebugorRelease(dotnet/efcore #38206). Thank you @m-x-shokhzod for this contribution!
- Model building
- File-scoped types can now be used as entity types without throwing
IndexOutOfRangeException(dotnet/efcore #38215). Thank you @m-x-shokhzod for this contribution! - Complex-property configuration lambdas can now chain into non-collection complex types (dotnet/efcore #38154).
- Conflicting-member errors now name the existing member kind and tell you to remove it first (dotnet/efcore #38222). Thank you @m-x-shokhzod for this contribution!
- File-scoped types can now be used as entity types without throwing
- Query diagnostics
- Using
EF.Constant()orEF.Parameter()inside compiled queries or query filters now throws a targetedInvalidOperationExceptioninstead of anInvalidCastException(dotnet/efcore #38155).
- Using
- SQLite scaffolding
- Reverse engineering a SQLite database now excludes EF Core's internal
__EFMigrationsLocktable, matching the existing behavior for__EFMigrationsHistory(dotnet/efcore #38169). Thank you @TomasMoralesBarr for this contribution!
- Reverse engineering a SQLite database now excludes EF Core's internal
Thank you to the community contributors who made EF Core better in this preview:
- @jjonescz:
Added file-based app support and
--file/--startup-fileoptions fordotnet ef(dotnet/efcore #38157, dotnet/efcore #38186). - @m-x-shokhzod: Added EF1004, fixed custom migration-bundle configurations, enabled file-scoped entity types, and improved conflicting-member errors (dotnet/efcore #38218, dotnet/efcore #38206, dotnet/efcore #38215, dotnet/efcore #38222).
- @TomasMoralesBarr:
Excluded
__EFMigrationsLockfrom SQLite scaffolding (dotnet/efcore #38169).