Delen via


Belangrijke wijzigingen in EF Core 8 (EF8)

Op deze pagina worden API's en gedragswijzigingen beschreven waarmee bestaande toepassingen kunnen worden onderbroken die worden bijgewerkt van EF Core 7 naar EF Core 8. Controleer eerdere belangrijke wijzigingen als u een eerdere versie van EF Core bijwerkt:

Standaardframework

EF Core 8 is gericht op .NET 8. Toepassingen die gericht zijn op oudere versies van .NET, .NET Core en .NET Framework, moeten worden bijgewerkt naar .NET 8.

Samenvatting

Incompatibele wijziging invloed
Contains in LINQ-query's werkt mogelijk niet meer op oudere SQL Server-versies Hoog
Mogelijke regressies in de prestaties van query's rond Contains in LINQ-query's Hoog
Enums in JSON worden standaard opgeslagen als ints in plaats van tekenreeksen Hoog
SQL Server-date en time ondersteunen nu scaffold naar .NET-DateOnly en TimeOnly- Gemiddeld
Booleaanse kolommen met een door de database gegenereerde waarde worden niet meer gescaffold als nullable Gemiddeld
SQLite Math methoden worden nu omgezet in SQL- Laag
ITypeBase vervangt IEntityType in sommige API's Laag
ValueGenerator-expressies moeten openbare API's gebruiken Laag
ExcludeFromMigrations sluit geen andere tabellen meer uit in een TPC-hiërarchie Laag
niet-schaduw gehele getallen worden bewaard in Cosmos-documenten Laag
Relationeel model wordt gegenereerd in het gecompileerde model Laag
Scaffolding kan verschillende navigatienamen genereren Laag
Discriminators beschikken nu over een maximale lengte Laag
SQL Server-sleutelwaarden worden hoofdletterongevoelig vergeleken Laag
Meerdere AddDbContext-aanroepen worden in verschillende volgorde toegepast Laag
EntityTypeAttributeConventionBase vervangen door TypeAttributeConventionBase Laag

Wijzigingen met hoge impact

Contains in LINQ-query's werkt mogelijk niet meer in oudere SQL Server-versies

Volgen van issue #13617

Oud gedrag

EF had speciale ondersteuning voor LINQ-query's met behulp van Contains operator via een lijst met geparameteriseerde waarden:

var names = new[] { "Blog1", "Blog2" };

var blogs = await context.Blogs
    .Where(b => names.Contains(b.Name))
    .ToArrayAsync();

Vóór EF Core 8.0 heeft EF de geparameteriseerde waarden als constanten in de SQL ingevoegd:

SELECT [b].[Id], [b].[Name]
FROM [Blogs] AS [b]
WHERE [b].[Name] IN (N'Blog1', N'Blog2')

Nieuw gedrag

Vanaf EF Core 8.0 genereert EF nu SQL die in veel gevallen efficiënter is, maar niet wordt ondersteund op SQL Server 2014 en hieronder:

SELECT [b].[Id], [b].[Name]
FROM [Blogs] AS [b]
WHERE [b].[Name] IN (
    SELECT [n].[value]
    FROM OPENJSON(@__names_0) WITH ([value] nvarchar(max) '$') AS [n]
)

Houd er rekening mee dat nieuwere SQL Server-versies kunnen worden geconfigureerd met een oudere compatibiliteitsniveau, waardoor ze ook niet compatibel zijn met de nieuwe SQL. Dit kan ook gebeuren met een Azure SQL-database die is gemigreerd van een eerder on-premises SQL Server-exemplaar, waarbij het oude compatibiliteitsniveau wordt overgedragen.

Waarom

Door de invoeging van constante waarden in de SQL ontstaan veel prestatieproblemen, waardoor het opslaan in cache van queryplannen wordt verslagen en onnodige verwijderingen van andere query's worden veroorzaakt. De nieuwe EF Core 8.0-vertaling maakt gebruik van de functie SQL Server OPENJSON om in plaats daarvan de waarden als een JSON-matrix over te dragen. Hiermee worden de prestatieproblemen opgelost die inherent zijn aan de vorige techniek; De OPENJSON-functie is echter niet beschikbaar in SQL Server 2014 en lager.

Zie dit blogbericht voor meer informatie over deze wijziging.

Maatregelen

Als uw database SQL Server 2016 (13.x) of hoger is, of als u Azure SQL gebruikt, controleert u het geconfigureerde compatibiliteitsniveau van uw database via de volgende opdracht:

SELECT name, compatibility_level FROM sys.databases;

Als het compatibiliteitsniveau lager is dan 130 (SQL Server 2016), kunt u overwegen het te wijzigen in een nieuwere waarde (documentatie).

Als uw databaseversie echt ouder is dan SQL Server 2016 of is ingesteld op een oud compatibiliteitsniveau dat u om een of andere reden niet kunt wijzigen, kunt u EF configureren om terug te keren naar de oudere, pre-8.0 SQL. Als u EF 9 gebruikt, kunt u de zojuist geïntroduceerde TranslateParameterizedCollectionsToConstantsgebruiken:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.UseSqlServer("<CONNECTION STRING>", o => o.TranslateParameterizedCollectionsToConstants())

Als u EF 8 gebruikt, kunt u hetzelfde effect bereiken wanneer u SQL Server gebruikt door het SQL-compatibiliteitsniveau van EF te configureren:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlServer(@"<CONNECTION STRING>", o => o.UseCompatibilityLevel(120));

Mogelijke regressies voor queryprestaties rond Contains in LINQ-query's

Probleem bijhouden #32394

Oud gedrag

EF had speciale ondersteuning voor LINQ-query's met behulp van Contains operator via een lijst met geparameteriseerde waarden:

var names = new[] { "Blog1", "Blog2" };

var blogs = await context.Blogs
    .Where(b => names.Contains(b.Name))
    .ToArrayAsync();

Vóór EF Core 8.0 heeft EF de geparameteriseerde waarden als constanten in de SQL ingevoegd:

SELECT [b].[Id], [b].[Name]
FROM [Blogs] AS [b]
WHERE [b].[Name] IN (N'Blog1', N'Blog2')

Nieuw gedrag

Vanaf EF Core 8.0 genereert EF nu het volgende:

SELECT [b].[Id], [b].[Name]
FROM [Blogs] AS [b]
WHERE [b].[Name] IN (
    SELECT [n].[value]
    FROM OPENJSON(@__names_0) WITH ([value] nvarchar(max) '$') AS [n]
)

Na de release van EF 8 bleek echter dat hoewel de nieuwe SQL in de meeste gevallen efficiënter is, het in een minderheid van gevallen aanzienlijk minder efficiënt kan zijn, zelfs in sommige gevallen waardoor querytime-outs ontstaan.

Zie deze opmerking voor een samenvatting van de wijziging in EF 8, de gedeeltelijke oplossingen die in EF 9 zijn verstrekt en het plan voor EF 10.

Maatregelen

Als u EF 9 gebruikt, kunt u de zojuist geïntroduceerde TranslateParameterizedCollectionsToConstants gebruiken om de Contains vertaling voor alle query's terug te zetten naar het pre-8.0-gedrag:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.UseSqlServer("<CONNECTION STRING>", o => o.TranslateParameterizedCollectionsToConstants())

Als u EF 8 gebruikt, kunt u hetzelfde effect bereiken wanneer u SQL Server gebruikt door het SQL-compatibiliteitsniveau van EF te configureren:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlServer(@"<CONNECTION STRING>", o => o.UseCompatibilityLevel(120));

Ten slotte kunt u de vertaling per query beheren met behulp van EF.Constant als volgt:

var blogs = await context.Blogs
    .Where(b => EF.Constant(names).Contains(b.Name))
    .ToArrayAsync();

Enums in JSON worden standaard opgeslagen als ints in plaats van tekenreeksen

bijhouden van probleem #13617

Oud gedrag

In EF7 worden opsommingen die zijn toegewezen aan JSON- standaard opgeslagen als tekenreekswaarden in het JSON-document.

Nieuw gedrag

Vanaf EF Core 8.0 worden enumeraties standaard als gehele getallen in het JSON-document in kaart gebracht.

Waarom

EF heeft standaard altijd opsommingen toegewezen aan een numerieke kolom in relationele databases. Omdat EF query's ondersteunt waarbij waarden uit JSON communiceren met waarden uit kolommen en parameters, is het belangrijk dat de waarden in JSON overeenkomen met de waarden in de niet-JSON-kolom.

Beperkingen

Als u tekenreeksen wilt blijven gebruiken, configureert u de enum-eigenschap met een conversie. Bijvoorbeeld:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>().Property(e => e.Status).HasConversion<string>();
}

Of voor alle eigenschappen van het enumtype::

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Properties<StatusEnum>().HaveConversion<string>();
}

Wijzigingen met gemiddelde impact

SQL Server date en time nu een scaffold naar .NET-DateOnly en TimeOnly

probleem bijhouden #24507

Oud gedrag

Voorheen zou EF bij het opzetten van een SQL Server-database met date of time kolommen entiteitseigenschappen genereren met typen DateTime en TimeSpan.

Nieuw gedrag

Vanaf EF Core 8.0 worden date en time als DateOnly en TimeOnlygegenereerd.

Waarom

DateOnly en TimeOnly zijn geïntroduceerd in .NET 6.0 en zijn een perfecte overeenkomst voor het toewijzen van de datum- en tijdtypen van de database. DateTime bevat met name een tijdonderdeel dat ongebruikt gaat en verwarring kan veroorzaken bij het toewijzen aan date, en TimeSpan vertegenwoordigt een tijdsinterval - mogelijk inclusief dagen - in plaats van een tijdstip waarop een gebeurtenis plaatsvindt. Het gebruik van de nieuwe typen voorkomt fouten en verwarring en biedt duidelijkheid van intentie.

Beperkende maatregelen

Deze wijziging is alleen van invloed op gebruikers die hun database regelmatig opnieuw in een EF-codemodel ('database-first'-stroom) herbouwen.

Het wordt aanbevolen om te reageren op deze wijziging door uw code aan te passen zodat de nieuw aangemaakte DateOnly- en TimeOnly-types worden gebruikt. Als dat echter niet mogelijk is, kunt u de scaffolding-sjablonen bewerken om terug te keren naar de vorige toewijzing. Om dit te doen, stelt u de sjablonen in zoals beschreven op deze pagina. Bewerk vervolgens het bestand EntityType.t4, zoek waar de entiteitseigenschappen worden gegenereerd (zoek naar property.ClrType) en wijzig de code in het volgende:

        var clrType = property.GetColumnType() switch
        {
            "date" when property.ClrType == typeof(DateOnly) => typeof(DateTime),
            "date" when property.ClrType == typeof(DateOnly?) => typeof(DateTime?),
            "time" when property.ClrType == typeof(TimeOnly) => typeof(TimeSpan),
            "time" when property.ClrType == typeof(TimeOnly?) => typeof(TimeSpan?),
            _ => property.ClrType
        };

        usings.AddRange(code.GetRequiredUsings(clrType));

        var needsNullable = Options.UseNullableReferenceTypes && property.IsNullable && !clrType.IsValueType;
        var needsInitializer = Options.UseNullableReferenceTypes && !property.IsNullable && !clrType.IsValueType;
#>
    public <#= code.Reference(clrType) #><#= needsNullable ? "?" : "" #> <#= property.Name #> { get; set; }<#= needsInitializer ? " = null!;" : "" #>
<#

Booleaanse kolommen met een door de database gegenereerde waarde worden niet meer als null-bestand weergegeven

Volgprobleem #15070

Oud gedrag

Voorheen werden niet-nulleerbare bool kolommen met een standaardbeperking voor de database als nullable bool?-eigenschappen weergegeven.

Nieuw gedrag

Vanaf EF Core 8.0 worden niet-nullable bool kolommen altijd als niet-nullable eigenschappen weergegeven.

Waarom

Een eigenschap bool zal zijn waarde niet naar de database sturen als deze waarde falseis, dat is de standaardwaarde van de CLR. Als de database een standaardwaarde van true heeft voor de kolom, maar de waarde van de eigenschap is false, eindigt de waarde in de database als true. In EF8 kan echter de sentinel die wordt gebruikt om te bepalen of een eigenschap een waarde heeft, worden gewijzigd. Dit wordt automatisch gedaan voor bool-eigenschappen waarvoor de database een waarde van truegenereert, wat betekent dat het niet langer nodig is om de eigenschappen als nullbaar te maken.

Maatregelen

Deze wijziging is alleen van invloed op gebruikers die hun database regelmatig opnieuw in een EF-codemodel ('database-first'-stroom) herbouwen.

Het wordt aanbevolen om te reageren op deze wijziging door de code te wijzigen om de niet-null-bare booleigenschap te gebruiken. Als dat echter niet mogelijk is, kunt u de scaffoldingsjablonen bewerken om de vorige toewijzing te herstellen. Hiervoor moet u de sjablonen instellen zoals beschreven op deze pagina. Bewerk vervolgens het bestand EntityType.t4, zoek waar de entiteitseigenschappen worden gegenereerd (zoek naar property.ClrType) en wijzig de code in het volgende:

#>
        var propertyClrType = property.ClrType != typeof(bool)
                              || (property.GetDefaultValueSql() == null && property.GetDefaultValue() != null)
            ? property.ClrType
            : typeof(bool?);
#>
    public <#= code.Reference(propertyClrType) #><#= needsNullable ? "?" : "" #> <#= property.Name #> { get; set; }<#= needsInitializer ? " = null!;" : "" #>
<#
<#

Wijzigingen met lage impact

SQLite Math methoden worden nu omgezet in SQL

Volgprobleem #18843

Oud gedrag

Voorheen werden alleen de methoden Abs, Max, Min en Round op Math vertaald naar SQL. Alle andere leden zouden op de client geëvalueerd worden als ze voorkwamen in de laatste Select-expressie van een query.

Nieuw gedrag

In EF Core 8.0 worden alle Math methoden met bijbehorende SQLite-wiskundige functies vertaald naar SQL.

Deze wiskundige functies zijn standaard ingeschakeld in de systeemeigen SQLite-bibliotheek (via onze afhankelijkheid van het SQLitePCLRaw.bundle_e_sqlite3 NuGet-pakket). Ze zijn ook ingeschakeld in de bibliotheek van SQLitePCLRaw.bundle_e_sqlcipher. Als u een van deze bibliotheken gebruikt, mag uw toepassing niet worden beïnvloed door deze wijziging.

Er is echter een kans dat toepassingen met inbegrip van de systeemeigen SQLite-bibliotheek op andere manieren de wiskundige functies niet mogelijk maken. In deze gevallen worden de Math-methoden naar SQL vertaald en treden er geen fouten op van het type 'geen dergelijke functie' wanneer ze worden uitgevoerd.

Waarom

SQLite heeft ingebouwde wiskundige functies toegevoegd in versie 3.35.0. Hoewel ze standaard zijn uitgeschakeld, zijn ze veel te veel geworden dat we hebben besloten om standaardvertalingen voor hen te bieden in onze EF Core SQLite-provider.

We hebben ook samengewerkt met Eric Sink aan het SQLitePCLRaw-project om wiskundige functies in te schakelen in alle systeemeigen SQLite-bibliotheken die deel uitmaken van dat project.

Oplossingen

De eenvoudigste manier om onderbrekingen op te lossen is, indien mogelijk, de wiskundige functies in de systeemeigen SQLite-bibliotheek in te schakelen door de compileeroptie SQLITE_ENABLE_MATH_FUNCTIONS op te geven.

Als u de compilatie van de systeemeigen bibliotheek niet bepaalt, kunt u ook onderbrekingen oplossen door tijdens runtime de functies te maken met behulp van de Microsoft.Data.Sqlite API's.

sqliteConnection
    .CreateFunction<double, double, double>(
        "pow",
        Math.Pow,
        isDeterministic: true);

U kunt ook client-evaluatie afdwingen door de Select-expressie te splitsen in twee delen, gescheiden door AsEnumerable.

// Before
var query = dbContext.Cylinders
    .Select(
        c => new
        {
            Id = c.Id
            // May throw "no such function: pow"
            Volume = Math.PI * Math.Pow(c.Radius, 2) * c.Height
        });

// After
var query = dbContext.Cylinders
    // Select the properties you'll need from the database
    .Select(
        c => new
        {
            c.Id,
            c.Radius,
            c.Height
        })
    // Switch to client-eval
    .AsEnumerable()
    // Select the final results
    .Select(
        c => new
        {
            Id = c.Id,
            Volume = Math.PI * Math.Pow(c.Radius, 2) * c.Height
        });

ITypeBase vervangt IEntityType in sommige API's

Volgprobleem #13947

Oud gedrag

Voorheen waren alle gemapte structurele typen entiteitstypen.

Nieuw gedrag

Met de introductie van complexe typen in EF8 gebruiken sommige API's die eerder een IEntityType nu ITypeBase gebruiken, zodat de API's kunnen worden gebruikt met entiteits- of complexe typen. Dit omvat:

  • IProperty.DeclaringEntityType is nu verouderd en IProperty.DeclaringType in plaats daarvan moet worden gebruikt.
  • IEntityTypeIgnoredConvention is nu verouderd en ITypeIgnoredConvention in plaats daarvan moet worden gebruikt.
  • IValueGeneratorSelector.Select accepteert nu een ITypeBase die kan zijn, maar niet hoeft te zijn een IEntityType.

Waarom

Met de introductie van complexe typen in EF8 kunnen deze API's worden gebruikt met IEntityType of IComplexType.

Maatregelen

De oude API's zijn buiten gebruik gesteld, maar worden niet verwijderd totdat EF10. Code moet worden bijgewerkt voor het gebruik van de nieuwe API's ASAP.

ValueConverter- en ValueComparer-expressies moeten openbare API's gebruiken voor het gecompileerde model

Volgprobleem #24896

Oud gedrag

Voorheen werden ValueConverter- en ValueComparer-definities niet opgenomen in het gecompileerde model en konden dus willekeurige code bevatten.

Nieuw gedrag

EF extraheert nu de expressies uit de ValueConverter- en ValueComparer-objecten en bevat deze C# in het gecompileerde model. Dit betekent dat deze expressies alleen openbare API mogen gebruiken.

Waarom

Het EF-team verplaatst geleidelijk meer constructies naar het gecompileerde model ter ondersteuning van het gebruik van EF Core met AOT in de toekomst.

Maatregelen

Maak de API's die door de comparer openbaar worden gebruikt. Denk bijvoorbeeld aan dit eenvoudige conversieprogramma:

public class MyValueConverter : ValueConverter<string, byte[]>
{
    public MyValueConverter()
        : base(v => ConvertToBytes(v), v => ConvertToString(v))
    {
    }

    private static string ConvertToString(byte[] bytes)
        => ""; // ... TODO: Conversion code

    private static byte[] ConvertToBytes(string chars)
        => Array.Empty<byte>(); // ... TODO: Conversion code
}

Als u dit conversieprogramma wilt gebruiken in een gecompileerd model met EF8, moeten de methoden ConvertToString en ConvertToBytes openbaar worden gemaakt. Bijvoorbeeld:

public class MyValueConverter : ValueConverter<string, byte[]>
{
    public MyValueConverter()
        : base(v => ConvertToBytes(v), v => ConvertToString(v))
    {
    }

    public static string ConvertToString(byte[] bytes)
        => ""; // ... TODO: Conversion code

    public static byte[] ConvertToBytes(string chars)
        => Array.Empty<byte>(); // ... TODO: Conversion code
}

ExcludeFromMigrations sluit geen andere tabellen meer uit in een TPC-hiërarchie

Volgprobleem #30079

Oud gedrag

Voorheen zou het gebruik van ExcludeFromMigrations voor een tabel in een TPC-hiërarchie ook andere tabellen in de hiërarchie uitsluiten.

Nieuw gedrag

Vanaf EF Core 8.0 heeft ExcludeFromMigrations geen invloed op andere tabellen.

Waarom

Het oude gedrag was een fout en verhinderde dat migraties worden gebruikt voor het beheren van hiërarchieën tussen projecten.

Maatregelen

Gebruik ExcludeFromMigrations expliciet in een andere tabel die moet worden uitgesloten.

Niet-schaduw gehele getal-sleutels worden opgeslagen in Cosmos-documenten

Volgprobleem #31664

Oud gedrag

Voorheen zouden niet-schaduw gehele getallen die voldoen aan de criteria die overeenkomen met een gesynthetiseerde sleuteleigenschap, niet worden bewaard in het JSON-document, maar werden in plaats daarvan opnieuw gesynthetiseerd op weg.

Nieuw gedrag

Vanaf EF Core 8.0 worden deze eigenschappen nu behouden.

Waarom

Het oude gedrag was een bug en verhinderde dat eigenschappen die voldeden aan de gesynthetiseerde sleutelcriteria, konden worden opgeslagen in Cosmos.

Maatregelen

de eigenschap uitsluiten van het model als de waarde niet moet worden behouden. Daarnaast kunt u dit gedrag volledig uitschakelen door Microsoft.EntityFrameworkCore.Issue31664 AppContext-switch in te stellen op true. Zie AppContext voor bibliotheekgebruikers voor meer informatie.

AppContext.SetSwitch("Microsoft.EntityFrameworkCore.Issue31664", isEnabled: true);

Relationeel model wordt gegenereerd in het gecompileerde model

traceerprobleem #24896

Oud gedrag

Voorheen werd het relationele model tijdens runtime berekend, zelfs bij het gebruik van een gecompileerd model.

Nieuw gedrag

Vanaf EF Core 8.0 maakt het relationele model deel uit van het gegenereerde gecompileerde model. Voor met name grote modellen kan het gegenereerde bestand echter niet worden gecompileerd.

Waarom

Dit is gedaan om de opstarttijd verder te verbeteren.

Oplossingen

Bewerk het gegenereerde bestand *ModelBuilder.cs en verwijder de regel AddRuntimeAnnotation("Relational:RelationalModel", CreateRelationalModel()); en de methode CreateRelationalModel().

Scaffolding kan verschillende navigatienamen genereren

Probleem #27832 bijhouden

Oud gedrag

Voorheen werden bij het genereren van een DbContext en het opstellen van entiteitstypen uit een bestaande database de navigatienamen voor relaties soms afgeleid van een gemeenschappelijk voorvoegsel van meerdere kolomnamen voor buitenlandse sleutels.

Nieuw gedrag

Vanaf EF Core 8.0 worden veelgebruikte voorvoegsels van kolomnamen van een samengestelde buitenlandse sleutel niet meer gebruikt om navigatienamen te genereren.

Waarom

Dit is een onduidelijke naamgevingsregel die soms zeer slechte namen genereert, zoals, S, Student_of zelfs gewoon _. Zonder deze regel worden vreemde namen niet meer gegenereerd en worden de naamconventies voor navigatie ook eenvoudiger gemaakt, waardoor het gemakkelijker wordt om te begrijpen en te voorspellen welke namen worden gegenereerd.

Maatregelen

De EF Core Power Tools hebben een optie om navigaties op de oude manier te blijven genereren. U kunt de gegenereerde code ook volledig aanpassen met T4-sjablonen. Dit kan worden gebruikt om de eigenschappen van buitenlandse sleutels in scaffolding-relaties te illustreren en de gepaste regel voor uw code te hanteren om de benodigde navigatienamen te genereren.

Discriminators hebben nu een maximale lengte

Volgprobleem #10691

Oud gedrag

Eerder waren de discriminatorkolommen die voor de TPH-overnametoewijzing van werden aangemaakt, geconfigureerd als nvarchar(max) op SQL Server/Azure SQL, of het equivalente onbegrensde tekenreekstype in andere databases.

Nieuw gedrag

Vanaf EF Core 8.0 worden discriminatorkolommen gemaakt met een maximale lengte die alle bekende discriminatorwaarden omvat. EF genereert een migratie om deze wijziging aan te brengen. Als de discriminatorkolom echter op een of andere manier wordt beperkt (bijvoorbeeld als onderdeel van een index), kan het AlterColumn dat is gemaakt door migraties mislukken.

Waarom

nvarchar(max) kolommen zijn inefficiënt en onnodig wanneer de lengte van alle mogelijke waarden bekend is.

Maatregelen

De kolomgrootte kan expliciet niet-afhankelijk worden gemaakt:

modelBuilder.Entity<Foo>()
    .Property<string>("Discriminator")
    .HasMaxLength(-1);

SQL Server-sleutelwaarden worden hoofdletterongevoelig vergeleken

probleem bijhouden #27526

Oud gedrag

Voorheen werden bij het bijhouden van entiteiten met tekenreekssleutels met de SQL Server-/Azure SQL-databaseproviders de sleutelwaarden vergeleken met behulp van de standaard .NET-hoofdlettergevoelige ordinale vergelijking.

Nieuw gedrag

Vanaf EF Core 8.0 worden sleutelwaarden voor tekenreeks voor SQL Server/Azure SQL vergeleken met behulp van de standaard .NET-hoofdletterongevoelige ordinale vergelijking.

Waarom

SQL Server maakt standaard gebruik van hoofdletterongevoelige vergelijkingen bij het vergelijken van vreemde sleutelwaarden voor overeenkomsten met principal-sleutelwaarden. Dit betekent dat wanneer EF hoofdlettergevoelige vergelijkingen gebruikt, een vreemde sleutel mogelijk niet aan een hoofdsleutel wordt gekoppeld wanneer dat zou moeten.

Oplossingen

Hoofdlettergevoelige vergelijkingen kunnen door het instellen van een aangepaste ValueComparergebruikt worden. Bijvoorbeeld:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    var comparer = new ValueComparer<string>(
        (l, r) => string.Equals(l, r, StringComparison.Ordinal),
        v => v.GetHashCode(),
        v => v);

    modelBuilder.Entity<Blog>()
        .Property(e => e.Id)
        .Metadata.SetValueComparer(comparer);

    modelBuilder.Entity<Post>(
        b =>
        {
            b.Property(e => e.Id).Metadata.SetValueComparer(comparer);
            b.Property(e => e.BlogId).Metadata.SetValueComparer(comparer);
        });
}

Meerdere AddDbContext-aanroepen worden in verschillende volgorde toegepast

bijhouden van probleem #32518

Oud gedrag

Voorheen, als er meerdere aanroepen naar AddDbContext, AddDbContextPool, AddDbContextFactory of AddPooledDbContextFactor werden gedaan met hetzelfde contexttype maar conflicterende configuratie, won de eerste.

Nieuw gedrag

Vanaf EF Core 8.0 heeft de configuratie van de laatste aanroep voorrang.

Waarom

Dit is gewijzigd zodat deze consistent is met de nieuwe methode ConfigureDbContext die kan worden gebruikt om configuratie toe te voegen vóór of na de Add* methoden.

Maatregelen

Keer de volgorde van oproepen van Add* om.

EntityTypeAttributeConventionBase vervangen door TypeAttributeConventionBase

Nieuw gedrag

In EF Core 8.0 is de naam van EntityTypeAttributeConventionBase gewijzigd in TypeAttributeConventionBase.

Waarom

TypeAttributeConventionBase vertegenwoordigt de functionaliteit beter, omdat deze nu kan worden gebruikt voor complexe typen en entiteitstypen.

Maatregelen

Vervang EntityTypeAttributeConventionBase gebruik door TypeAttributeConventionBase.