Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This page documents API and behavior changes that have the potential to break existing applications updating from EF Core 10 to EF Core 11. Make sure to review earlier breaking changes if updating from an earlier version of EF Core:
Summary
Note
If you are using Microsoft.Data.Sqlite, please see the separate section below on Microsoft.Data.Sqlite breaking changes.
Medium-impact changes
Sync I/O via the Azure Cosmos DB provider has been fully removed
Old behavior
Synchronous I/O via the Azure Cosmos DB provider has been unsupported since EF 9.0 (note); calling any sync I/O API - like ToList or SaveChanges threw an exception, unless a special opt-in was configured. When the opt-in was configured, sync I/O APIs worked as before, causing the provider to perform "sync-over-async" blocking against the Azure Cosmos DB SDK, which could result in deadlocks and other performance issues.
New behavior
Starting with EF Core 11.0, EF now always throws when a synchronous I/O API is called. There is no way to opt back into using sync I/O APIs.
Why
Synchronous blocking on asynchronous methods ("sync-over-async") is highly discouraged, and can lead to deadlock and other performance problems. Since the Azure Cosmos DB SDK only supports async methods, so does the EF Cosmos provider.
Mitigations
Convert your code to use async I/O APIs instead of sync I/O ones. For example, replace calls to SaveChanges() with await SaveChangesAsync().
Microsoft.Data.SqlClient has been updated to 7.0
Old behavior
EF Core 10 used Microsoft.Data.SqlClient 6.x, which included Azure/Entra ID authentication dependencies (such as Azure.Core, Azure.Identity, and Microsoft.Identity.Client) in the core package.
New behavior
EF Core 11 now depends on Microsoft.Data.SqlClient 7.0. This version removes Azure/Entra ID (formerly Azure Active Directory) authentication dependencies from the core package. If your application uses Entra ID authentication (for example, ActiveDirectoryDefault, ActiveDirectoryInteractive, ActiveDirectoryManagedIdentity, or ActiveDirectoryServicePrincipal), you must now install the Microsoft.Data.SqlClient.Extensions.Azure package separately.
In addition, SqlAuthenticationMethod.ActiveDirectoryPassword has been marked as obsolete.
For more details, see the Microsoft.Data.SqlClient 7.0 release notes.
Why
This change was made in Microsoft.Data.SqlClient to reduce dependency bloat for applications that don't use Azure authentication, which is especially beneficial for containerized deployments and local development.
Mitigations
If your application uses Entra ID authentication with SQL Server, add a reference to the Microsoft.Data.SqlClient.Extensions.Azure package in your project:
<PackageReference Include="Microsoft.Data.SqlClient.Extensions.Azure" Version="7.0.0" />
No code changes are required beyond adding this package reference. If you use SqlAuthenticationMethod.ActiveDirectoryPassword, migrate to a modern authentication method such as ActiveDirectoryDefault or ActiveDirectoryInteractive.
Low-impact changes
EF Core now throws by default when no migrations are found
Old behavior
Previously, when calling Migrate or MigrateAsync on a database with no migrations in the assembly, EF Core logged an informational message and returned without applying any changes.
New behavior
Starting with EF Core 11.0, EF Core throws an exception by default when no migrations are found in the assembly. This is consistent with the PendingModelChangesWarning behavior introduced in EF 9.0.
Why
Calling Migrate() or MigrateAsync() when no migrations exist typically indicates a misconfiguration. Rather than silently continuing and leaving the database in a potentially incorrect state, EF Core now alerts developers to this issue immediately.
Mitigations
If you intentionally call Migrate() without having any migrations (for example, because you manage the database schema through other means), remove the Migrate() call or suppress the exception by configuring warnings:
options.ConfigureWarnings(w => w.Ignore(RelationalEventId.MigrationsNotFound))
Or to log the event instead of throwing:
options.ConfigureWarnings(w => w.Log(RelationalEventId.MigrationsNotFound))
EFOptimizeContext MSBuild property has been removed
Old behavior
Previously, the EFOptimizeContext MSBuild property could be set to true to enable compiled model and precompiled query code generation during build or publish:
<EFOptimizeContext Condition="'$(Configuration)'=='Release'">true</EFOptimizeContext>
New behavior
Starting with EF Core 11.0, the EFOptimizeContext MSBuild property has been removed. Code generation is now controlled exclusively through the EFScaffoldModelStage and EFPrecompileQueriesStage properties. When PublishAOT is set to true, code generation is automatically enabled during publish without needing any additional property.
Why
The EFScaffoldModelStage and EFPrecompileQueriesStage properties already provide fine-grained control over when code generation occurs. EFOptimizeContext was a redundant enablement gate.
Mitigations
Replace usages of EFOptimizeContext with the EFScaffoldModelStage and EFPrecompileQueriesStage properties. These can be set to publish or build to control at which stage code generation occurs:
<EFScaffoldModelStage>publish</EFScaffoldModelStage>
<EFPrecompileQueriesStage>publish</EFPrecompileQueriesStage>
Any other value (for example, none) disables the corresponding generation.
If you have PublishAOT set to true, code generation is automatically enabled during publish and no additional configuration is needed.
EF tools packages no longer reference Microsoft.EntityFrameworkCore.Design
Old behavior
Previously, the Microsoft.EntityFrameworkCore.Tools and Microsoft.EntityFrameworkCore.Tasks NuGet packages had a dependency on Microsoft.EntityFrameworkCore.Design.
New behavior
Starting with EF Core 11.0, the Microsoft.EntityFrameworkCore.Tools and Microsoft.EntityFrameworkCore.Tasks NuGet packages no longer have a dependency on Microsoft.EntityFrameworkCore.Design.
Why
There was no hard dependency on the code in Microsoft.EntityFrameworkCore.Design, and this dependency was causing issues when using the latest Microsoft.EntityFrameworkCore.Tools with projects targeting older frameworks.
Mitigations
If your project relies on Microsoft.EntityFrameworkCore.Design being brought in transitively through the tools packages, add a direct reference to it in your project:
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="11.0.0" PrivateAssets="all" />
SqlVector properties are no longer loaded by default
Old behavior
Previously, when querying entities with SqlVector<T> properties, EF Core included the vector column in SELECT statements and populated the property on the returned entity.
New behavior
Starting with EF Core 11.0, SqlVector<T> properties are no longer included in SELECT statements when materializing entities. The property will be null on returned entities.
Vector properties can still be used in WHERE and ORDER BY clauses—including with VectorDistance() and VectorSearch(); they just won't be included in the entity projection.
Why
Vector columns can be very large, containing hundreds or thousands of floating-point values. In the vast majority of cases, vectors are written to the database and then used for search, without needing to be read back. Excluding them from SELECT by default avoids unnecessary data transfer.
Mitigations
Note
A mechanism for opting vector properties back into automatic loading will be introduced later in the EF Core 11 release.
If you need to read back vector values, use an explicit projection:
var embeddings = await context.Blogs
.Select(b => new { b.Id, b.Embedding })
.ToListAsync();
Cosmos: empty owned collections now return an empty collection instead of null
Old behavior
Previously, when querying entities via the Azure Cosmos DB provider where an owned collection contained no items, the collection property was null on the materialized entity.
New behavior
Starting with EF Core 11.0, the Azure Cosmos DB provider correctly initializes empty owned collections, returning an empty collection instead of null.
Why
The previous behavior of materializing empty owned collections as null was a bug.
Mitigations
If your code explicitly checks owned collection properties for null to detect that the collection is empty, those checks can simply be removed, since the collection is now always initialized:
// Before
if (entity.OwnedCollection is null or { Count: 0 })
{
// treated as empty
}
// After
if (entity.OwnedCollection is { Count: 0 })
{
// treated as empty
}
Microsoft.Data.Sqlite breaking changes
Note
SQLitePCLRaw is an external, community-maintained library that is not owned or maintained by Microsoft. Microsoft.Data.Sqlite depends on it for its SQLite connectivity.
Summary
| Breaking change | Impact |
|---|---|
| Encryption-enabled SQLite packages have been removed | Medium |
| Some SQLitePCLRaw bundle packages have been removed | Medium |
Medium-impact changes
Encryption-enabled SQLite packages have been removed
Old behavior
Previously, the SQLitePCLRaw.bundle_e_sqlcipher NuGet package provided encryption-enabled SQLite builds at no cost.
New behavior
Starting with SQLitePCLRaw 3.0 (used by Microsoft.Data.Sqlite 11.0), the SQLitePCLRaw.bundle_e_sqlcipher package has been deprecated and removed from NuGet. No-cost encryption-enabled SQLite builds are no longer distributed.
Why
The previous no-cost SQLitePCLRaw.bundle_e_sqlcipher package was barely maintained, which is a significant concern for encryption software where security vulnerabilities may go unpatched. The SQLitePCLRaw maintainer removed these builds in version 3.0 in favor of professionally maintained, paid alternatives that provide ongoing security updates.
Mitigations
If you need SQLite encryption, you have the following options:
- SQLite Encryption Extension (SEE): This is the official encryption implementation from the SQLite team. A paid license is required. See https://sqlite.org/com/see.html for details. NuGet packages are available through SourceGear's SQLite build service.
- SQLCipher: Purchase supported builds from Zetetic, or build the open source code yourself.
- SQLite3 Multiple Ciphers: NuGet packages are available from SQLite3MultipleCiphers-NuGet.
- When encrypting a new database or opening an existing database that was encrypted with SQLCipher, you must configure the cipher scheme in the connection string using URI parameters—for example:
Data Source=file:example.db?cipher=sqlcipher&legacy=4;Password=<password>. See How to open an existing database encrypted with SQLCipher for details.
- When encrypting a new database or opening an existing database that was encrypted with SQLCipher, you must configure the cipher scheme in the connection string using URI parameters—for example:
For more details, see SQLite encryption options for use with SQLitePCLRaw and SQLitePCLRaw 3.0 Release Notes.
Some SQLitePCLRaw bundle packages have been removed
Old behavior
Previously, the SQLitePCLRaw.bundle_sqlite3, SQLitePCLRaw.bundle_winsqlite3, SQLitePCLRaw.bundle_green, and SQLitePCLRaw.bundle_e_sqlite3mc packages provided a convenient way to configure SQLitePCLRaw with the corresponding SQLite provider.
New behavior
Starting with SQLitePCLRaw 3.0 (used by Microsoft.Data.Sqlite 11.0), these bundle packages have been removed. If your application depended on one of these bundles, you must now reference the corresponding provider package and explicitly initialize it.
Why
Each of these bundle packages contained only a single line of configuration code and added unnecessary packaging overhead. The corresponding provider packages are still supported.
Mitigations
Replace the removed bundle package with the corresponding provider package and add explicit initialization code.
If using bundle_sqlite3 or bundle_winsqlite3, replace the package reference:
<!-- Old -->
<PackageReference Include="SQLitePCLRaw.bundle_sqlite3" Version="2.x.x" />
<!-- or -->
<PackageReference Include="SQLitePCLRaw.bundle_winsqlite3" Version="2.x.x" />
<!-- New -->
<PackageReference Include="SQLitePCLRaw.provider.sqlite3" Version="3.x.x" />
<!-- or -->
<PackageReference Include="SQLitePCLRaw.provider.winsqlite3" Version="3.x.x" />
Then add explicit initialization before using SQLite:
// For sqlite3
static void Init()
{
SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3());
}
// For winsqlite3
static void Init()
{
SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_winsqlite3());
}
If using bundle_green, the recommended migration path is to switch to SQLitePCLRaw.bundle_e_sqlite3. Alternatively, use SQLitePCLRaw.config.e_sqlite3 paired with a separate native library package like SourceGear.sqlite3, which allows you to update the SQLite version independently:
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.x.x" />
If you only target iOS and want to continue using the system SQLite library, reference the provider directly:
<PackageReference Include="SQLitePCLRaw.core" Version="3.x.x" />
<PackageReference Include="SQLitePCLRaw.provider.sqlite3" Version="3.x.x" />
And initialize it explicitly:
static void Init()
{
SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3());
}
Note
If you are using SQLitePCLRaw.bundle_e_sqlite3, no changes are required—just update the version number. See the SQLitePCLRaw 3.0 Release Notes for details.