Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ Compiled models have some limitations:

* [Global query filters are not supported](https://github.com/dotnet/efcore/issues/24897).
* [Lazy loading and change-tracking proxies are not supported](https://github.com/dotnet/efcore/issues/24902).
* [Value converters that reference private methods are not supported](#value-converters-private-methods). Make referenced methods public or internal instead.
* [The model must be manually synchronized by regenerating it any time the model definition or configuration change](https://github.com/dotnet/efcore/issues/24894).
* Custom IModelCacheKeyFactory implementations are not supported. However, you can compile multiple models and load the appropriate one as needed.

Expand Down
168 changes: 168 additions & 0 deletions entity-framework/core/what-is-new/ef-core-10.0/breaking-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ This page documents API and behavior changes that have the potential to break ex
|:--------------------------------------------------------------------------------------------------------------- | -----------|
| [SQL Server json data type used by default on Azure SQL and compatibility level 170](#sqlserver-json-data-type) | Low |
| [ExecuteUpdateAsync now accepts a regular, non-expression lambda](#ExecuteUpdateAsync-lambda) | Low |
| [Compiled models now throw exception for value converters with private methods](#compiled-model-private-methods) | Low |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please align indentation here so that the markdown table is formatted correctly/consistently.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the markdown table indentation alignment. (94791e4)

| [Complex type column names are now uniquified](#complex-type-column-uniquification) | Low |
| [IDiscriminatorPropertySetConvention signature changed](#discriminator-convention-signature) | Low |
| [Nested complex type properties use full path in column names](#nested-complex-type-column-names) | Low |

## Low-impact changes

Expand Down Expand Up @@ -178,6 +182,170 @@ await context.Blogs.ExecuteUpdateAsync(s =>
});
```

<a name="compiled-model-private-methods"></a>

### Compiled models now throw exception for value converters with private methods

[Tracking Issue #35033](https://github.com/dotnet/efcore/issues/35033)

#### Old behavior

Previously, when using value converters with compiled models (using `dotnet ef dbcontext optimize`), EF would reference the converter type and everything worked correctly.

```c#
public sealed class BooleanToCharConverter : ValueConverter<bool, char>
{
public static readonly BooleanToCharConverter Default = new();

public BooleanToCharConverter()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe modernize the code sample a bit, with a primary constructor, expression-bodied methods below?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot modernize the code sample a bit, with a primary constructor and expression-bodied methods

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modernized the code sample to use a primary constructor and expression-bodied methods for the conversion methods. (1d1a23e)

: base(v => ConvertToChar(v), v => ConvertToBoolean(v))
{
}

private static char ConvertToChar(bool value) // Private method
{
return value ? 'Y' : 'N';
}

private static bool ConvertToBoolean(char value) // Private method
{
return value == 'Y';
}
}
```

Running `dotnet ef dbcontext optimize` would generate code that attempted to reference these private methods, causing CS0122 compilation errors.

#### New behavior

Starting with EF Core 10.0, EF generates code that directly references the conversion methods themselves. If these methods are private, compilation will fail.

#### Why

This change improves performance by generating more direct code, but requires that conversion methods be accessible to the generated code.

#### Mitigations

Make the methods referenced by value converters public or internal instead of private:

```c#
public sealed class BooleanToCharConverter : ValueConverter<bool, char>
{
public static readonly BooleanToCharConverter Default = new();

public BooleanToCharConverter()
: base(v => ConvertToChar(v), v => ConvertToBoolean(v))
{
}

public static char ConvertToChar(bool value) // Now public
{
return value ? 'Y' : 'N';
}

public static bool ConvertToBoolean(char value) // Now public
{
return value == 'Y';
}
}
```

<a name="complex-type-column-uniquification"></a>

### Complex type column names are now uniquified

[Tracking Issue #4970](https://github.com/dotnet/EntityFramework.Docs/issues/4970)

#### Old behavior

Previously, when mapping complex types to table columns, if multiple complex type properties had the same column name, they would silently share the same column.

#### New behavior

Starting with EF Core 10.0, complex type column names are uniquified by appending a number at the end if another column with the same name exists on the table.

#### Why

This prevents data corruption that could occur when multiple properties unintentionally mapped to the same column.

#### Mitigations

If you need specific column names, configure them explicitly:

```c#
modelBuilder.Entity<Customer>(b =>
{
b.ComplexProperty(c => c.ShippingAddress, p => p.Property(a => a.Street).HasColumnName("ShippingStreet"));
b.ComplexProperty(c => c.BillingAddress, p => p.Property(a => a.Street).HasColumnName("BillingStreet"));
});
```

<a name="discriminator-convention-signature"></a>

### IDiscriminatorPropertySetConvention signature changed

[Tracking Issue #4970](https://github.com/dotnet/EntityFramework.Docs/issues/4970)

#### Old behavior

Previously, `IDiscriminatorPropertySetConvention.ProcessDiscriminatorPropertySet` took `IConventionEntityTypeBuilder` as a parameter.

#### New behavior

Starting with EF Core 10.0, the method signature changed to take `IConventionTypeBaseBuilder` instead of `IConventionEntityTypeBuilder`.

#### Why

This change allows the convention to work with both entity types and complex types.

#### Mitigations

Update your custom convention implementations to use the new signature:

```c#
public virtual void ProcessDiscriminatorPropertySet(
IConventionTypeBaseBuilder typeBaseBuilder, // Changed from IConventionEntityTypeBuilder
string name,
Type type,
MemberInfo memberInfo,
IConventionContext<IConventionProperty> context)
```

<a name="nested-complex-type-column-names"></a>

### Nested complex type properties use full path in column names

[Tracking Issue #4947](https://github.com/dotnet/EntityFramework.Docs/issues/4947)

#### Old behavior

Previously, properties on nested complex types were mapped to columns using just the declaring type name. For example, `EntityType.Owned.Complex.Property` was mapped to column `Complex_Property`.

#### New behavior

Starting with EF Core 10.0, properties on nested complex types use the full path to the property as part of the column name. For example, `EntityType.Owned.Complex.Property` is now mapped to column `Owned_Complex_Property`.

#### Why

This provides better column name uniqueness and makes it clearer which property maps to which column.

#### Mitigations

If you need to maintain the old column names, configure them explicitly:

```c#
modelBuilder.Entity<EntityType>(b =>
{
b.ComplexProperty(e => e.Owned, owned =>
{
owned.ComplexProperty(o => o.Complex, complex =>
{
complex.Property(c => c.Property).HasColumnName("Complex_Property");
});
});
});
```

<a name="MDS-breaking-changes"></a>

## Microsoft.Data.Sqlite breaking changes
Expand Down