diff --git a/entity-framework/core/what-is-new/ef-core-6.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-6.0/breaking-changes.md index 104c6ffc2d..8019cdf8b9 100644 --- a/entity-framework/core/what-is-new/ef-core-6.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-6.0/breaking-changes.md @@ -44,6 +44,7 @@ EF Core 6.0 targets .NET 6. Applications targeting older .NET, .NET Core, and .N | [Default table mapping is not removed when the entity is mapped to a table-valued function](#tvf-default-mapping) | Low | | [dotnet-ef targets .NET 6](#dotnet-ef) | Low | | [`IModelCacheKeyFactory` implementations may need to be updated to handle design-time caching](#model-cache-key) | Low | +| [`NavigationBaseIncludeIgnored` is now an error by default](#ignored-navigation) | Low | \* These changes are of particular interest to authors of database providers and extensions. @@ -944,3 +945,32 @@ public object Create(DbContext context, bool designTime) ? (context.GetType(), dynamicContext.UseIntProperty, designTime) : (object)context.GetType(); ``` + +The navigation '{navigation}' was ignored from 'Include' in the query since the fix-up will automatically populate it. If any further navigations are specified in 'Include' afterwards then they will be ignored. Walking back include tree is not allowed. + + + +### `NavigationBaseIncludeIgnored` is now an error by default + +[Tracking Issue #4315](https://github.com/dotnet/EntityFramework.Docs/issues/4315) + +#### Old behavior + +The event `CoreEventId.NavigationBaseIncludeIgnored` was logged as a warning by default. + +#### New behavior + +The event `CoreEventId.NavigationBaseIncludeIgnored` was logged as an error by default and causes an exception to be thrown. + +#### Why + +These query patterns are not allowed, so EF Core now throws to indicate that the queries should be updated. + +#### Mitigations + +The old behavior can be restored by configuring the event as a warning. For example: + +```csharp +protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder.ConfigureWarnings(b => b.Warn(CoreEventId.NavigationBaseIncludeIgnored)); +``` diff --git a/entity-framework/core/what-is-new/ef-core-7.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-7.0/breaking-changes.md index 45761fae4b..61a315a0ea 100644 --- a/entity-framework/core/what-is-new/ef-core-7.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-7.0/breaking-changes.md @@ -131,11 +131,21 @@ The performance improvements linked to the new method are significant enough tha #### Mitigations -You can let EF Core know that the target table has a trigger; doing so will revert to the previous, less efficient technique. This can be done by configuring the corresponding entity type as follows: +If the target table has a trigger, then you can let EF Core know this, and EF will revert to the previous, less efficient technique. This can be done by configuring the corresponding entity type as follows: [!code-csharp[Main](../../../../samples/core/SqlServer/Misc/TriggersContext.cs?name=TriggerConfiguration&highlight=4)] -Note that doing this doesn't actually make EF Core create or manage the trigger in any way - it currently only informs EF Core that triggers are present on the table. As a result, any trigger name can be used, and this can also be used if an unsupported computed column is in use (regardless of triggers). +Note that doing this doesn't actually make EF Core create or manage the trigger in any way - it currently only informs EF Core that triggers are present on the table. As a result, any trigger name can be used. + +Specifying a trigger can be used to revert the old behavior, _even if there isn't actually a trigger in the table_. However, starting with EF Core 8.0, the use or not of the "OUTPUT" clause can configured explicitly, regardless of triggers. For example: + +```csharp +protected override void OnModelCreating(ModelBuilder modelBuilder) +{ + modelBuilder.Entity() + .ToTable(tb => tb.UseSqlOutputClause(false)); +} +``` If most or all of your tables have triggers, you can opt out of using the newer, efficient technique for all your model's tables by using the following model building convention: @@ -167,7 +177,17 @@ The simplifications and performance improvements linked to the new method are si #### Mitigations -In EF Core 8.0, a mechanism will be introduced that will allow specifying whether to use the new mechanism on a table-by-table basis. With EF Core 7.0, it's possible to revert to the old mechanism for the entire application by inserting the following code in your context configuration: +In EF Core 8.0, the `UseSqlReturningClause` method has been introduced to explicitly revert back to the older, less efficient SQL. For example: + +```csharp +protected override void OnModelCreating(ModelBuilder modelBuilder) +{ + modelBuilder.Entity() + .ToTable(tb => tb.UseSqlReturningClause(false)); +} +``` + +If you are still using EF Core 7.0, then it's possible to revert to the old mechanism for the entire application by inserting the following code in your context configuration: ```c# protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) @@ -493,11 +513,11 @@ Query or attach entities before marking entities as `Deleted`, or manually set n #### Old behavior -In EF Core 6.0, using the Azure Cosmos DB extension method when using a relational provider, or the relational extension method when using the Azure Cosmos DB provider could silently fail. +In EF Core 6.0, using the Azure Cosmos DB extension method when using a relational provider, or the relational extension method when using the Azure Cosmos DB provider could silently fail. Likewise, using relational methods on the in-memory provider is a silent no-op. #### New behavior -Starting with EF Core 7.0, using the wrong extension method will throw an exception. +Starting with EF Core 7.0, using an extension method designed for one provider on a different provider will throw an exception. #### Why diff --git a/entity-framework/core/what-is-new/ef-core-8.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-8.0/breaking-changes.md index ede5d0875d..50b25d840b 100644 --- a/entity-framework/core/what-is-new/ef-core-8.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-8.0/breaking-changes.md @@ -31,6 +31,9 @@ EF Core 8 targets .NET 8. Applications targeting older .NET, .NET Core, and .NET | [ExcludeFromMigrations no longer excludes other tables in a TPC hierarchy](#exclude-from-migrations) | Low | | [Non-shadow integer keys are persisted to Cosmos documents](#persist-to-cosmos) | Low | | [Relational model is generated in the compiled model](#compiled-relational-model) | Low | +| [Scaffolding may generate different navigation names](#navigation-names) | Low | +| [Discriminators now have a max length](#discriminators) | Low | +| [SQL Server key values are compared case-insensitively](#casekeys) | Low | ## High-impact changes @@ -437,3 +440,96 @@ This was done to further improve startup time. #### Mitigations Edit the generated `*ModelBuilder.cs` file and remove the line `AddRuntimeAnnotation("Relational:RelationalModel", CreateRelationalModel());` as well as the method `CreateRelationalModel()`. + + + +### Scaffolding may generate different navigation names + +[Tracking Issue #27832](https://github.com/dotnet/efcore/issues/27832) + +#### Old behavior + +Previously when scaffolding a `DbContext` and entity types from an existing database, the navigation names for relationships were sometimes derived from a common prefix of multiple foreign key column names. + +#### New behavior + +Starting with EF Core 8.0, common prefixes of column names from a composite foreign key are no longer used to generate navigation names. + +#### Why + +This is an obscure naming rule which sometimes generates very poor names like, `S`, `Student_`, or even just `_`. Without this rule, strange names are no longer generated, and the naming conventions for navigations are also made simpler, thereby making it easier to understand and predict which names will be generated. + +#### Mitigations + +The [EF Core Power Tools](https://github.com/ErikEJ/EFCorePowerTools/issues/2143) have an option to keep generating navigations in the old way. Alternatively, the code generated can be fully customized using [T4 templates](xref:core/managing-schemas/scaffolding/templates). This can be used to example the foreign key properties of scaffolding relationships and use whatever rule is appropriate for your code to generate the navigation names you need. + + + +### Discriminators now have a max length + +[Tracking Issue #10691](https://github.com/dotnet/efcore/issues/10691) + +#### Old behavior + +Previously, discriminator columns created for [TPH inheritance mapping](xref:core/modeling/inheritance) were configured as `nvarchar(max)` on SQL Server/Azure SQL, or the equivalent unbounded string type on other databases. + +#### New behavior + +Starting with EF Core 8.0, discriminator columns are created with a max length that covers all the known discriminator values. If the discriminator column is constrained in some way--for example, as part of an index--then the `AlterColumn` created by Migrations may fail. + +#### Why + +`nvarchar(max)` columns are inefficient and unnecessary when the lengths of all possible values are known. + +#### Mitigations + +The column size can be made explicitly unbounded: + +```csharp +modelBuilder.Entity() + .Property("Discriminator") + .HasMaxLength(-1); +``` + + + +### SQL Server key values are compared case-insensitively + +[Tracking Issue #27526](https://github.com/dotnet/efcore/issues/27526) + +#### Old behavior + +Previously, when tracking entities with string keys with the SQL Server/Azure SQL database providers, the key values were compared using the default .NET case-sensitive ordinal comparer. + +#### New behavior + +Starting with EF Core 8.0, SQL Server/Azure SQL string key values are compared using the default .NET case-insensitive ordinal comparer. + +#### Why + +By default, SQL Server uses case-insensitive comparisons when comparing foreign key values for matches to principal key values. This means when EF uses case-sensitive comparisons it may not connect a foreign key to a principal key when it should. + +#### Mitigations + +Case-sensitive comparisons can be used by setting a custom `ValueComparer`. For example: + +```csharp +protected override void OnModelCreating(ModelBuilder modelBuilder) +{ + var comparer = new ValueComparer( + (l, r) => string.Equals(l, r, StringComparison.Ordinal), + v => v.GetHashCode(), + v => v); + + modelBuilder.Entity() + .Property(e => e.Id) + .Metadata.SetValueComparer(comparer); + + modelBuilder.Entity( + b => + { + b.Property(e => e.Id).Metadata.SetValueComparer(comparer); + b.Property(e => e.BlogId).Metadata.SetValueComparer(comparer); + }); +} +```