Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Op deze pagina worden API's en gedragswijzigingen beschreven die het potentieel hebben om bestaande toepassingen te onderbreken die worden bijgewerkt van EF Core 8 naar EF Core 9. Controleer eerdere belangrijke wijzigingen als u een eerdere versie van EF Core bijwerkt:
- Ingrijpende wijzigingen in EF Core 8
- Belangrijke wijzigingen in EF Core 7
- Brekende wijzigingen in EF Core 6
Doelplatform
EF Core 9 richt zich op .NET 8. Dit betekent dat bestaande toepassingen die gericht zijn op .NET 8, dit kunnen blijven doen. Toepassingen die gericht zijn op oudere versies van .NET, .NET Core en .NET Framework, moeten zich richten op .NET 8 of .NET 9 om EF Core 9 te kunnen gebruiken.
Samenvatting
Notitie
Als u Azure Cosmos DB gebruikt, raadpleegt u de sectie aparte hieronder over Azure Cosmos DB breaking changes.
Wijzigingen met hoge impact
Er wordt een uitzondering gegenereerd bij het toepassen van migraties als er modelwijzigingen in behandeling zijn
Oud gedrag
Als het model wijzigingen in behandeling heeft vergeleken met de laatste migratie, worden deze niet toegepast met de rest van de migraties wanneer Migrate wordt aangeroepen.
Nieuw gedrag
Vanaf EF Core 9.0 wordt, als het model wijzigingen in behandeling heeft vergeleken met de laatste migratie, een uitzondering gegenereerd wanneer dotnet ef database update, Migrate of MigrateAsync wordt aangeroepen:
Het model voor context DbContext heeft wijzigingen die in behandeling zijn. Voeg een nieuwe migratie toe voordat u de database bijwerkt. Deze uitzondering kan worden onderdrukt of geregistreerd door gebeurtenis-id 'RelationalEventId.PendingModelChangesWarning' door te geven aan de methode ConfigureWarnings in DbContext.OnConfiguring of AddDbContext.
Waarom
Vergeet een nieuwe migratie toe te voegen nadat u modelwijzigingen hebt aangebracht, is een veelvoorkomende fout die in sommige gevallen moeilijk kan worden vastgesteld. De nieuwe uitzondering zorgt ervoor dat het model van de app overeenkomt met de database nadat de migraties zijn toegepast.
Maatregelen
Er zijn verschillende veelvoorkomende situaties waarin deze uitzondering kan worden gegenereerd:
Er zijn helemaal geen migraties. Dit is gebruikelijk wanneer de database op andere manieren wordt bijgewerkt.
- Risicobeperking: als u niet van plan bent om migraties te gebruiken voor het beheer van het databaseschema, verwijdert u de Migrate of MigrateAsync aanroep, anders voegt u een migratie toe.
Er is ten minste één migratie, maar de momentopname van het model ontbreekt. Dit is gebruikelijk voor migraties die handmatig zijn gemaakt.
- Mitigation: Voeg een nieuwe migratie toe met EF-hulpprogramma's. Dit zal de momentopname van het datamodel bijwerken.
Het model is niet gewijzigd door de ontwikkelaar, maar het is gebouwd op een niet-deterministische manier waardoor EF het kan detecteren als gewijzigd. Dit komt vaak voor wanneer
new DateTime(),DateTime.Now,DateTime.UtcNowofGuid.NewGuid()worden gebruikt in objecten die aan HasDataworden geleverd.- Risicobeperking: voeg een nieuwe migratie toe, bekijk de inhoud ervan om de oorzaak te vinden en vervang de dynamische gegevens door een statische, vastgelegde waarde in het model. De migratie moet opnieuw worden gemaakt nadat het model is opgelost. Als dynamische gegevens moeten worden gebruikt voor seeding, kunt u overwegen het nieuwe seedingpatroon te gebruiken in plaats van HasData.
De laatste migratie is gemaakt voor een andere provider dan degene die is gebruikt om de migraties toe te passen.
- Risicobeperking: dit is een niet-ondersteund scenario. De waarschuwing kan worden onderdrukt met behulp van het onderstaande codefragment, maar dit scenario werkt waarschijnlijk niet meer in een toekomstige EF Core-release. De aanbevolen oplossing is voor het genereren van een afzonderlijke set migraties voor elke provider.
De migraties worden dynamisch gegenereerd, gewijzigd of gekozen door enkele EF-services te vervangen.
-
Risicobeperking: de waarschuwing is in dit geval een vals alarm en moet worden genegeerd.
options.ConfigureWarnings(w => w.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning))
-
Risicobeperking: de waarschuwing is in dit geval een vals alarm en moet worden genegeerd.
U gebruikt ASP.NET Core Identiteit en wijzigopties die van invloed zijn op het model, zoals:
.AddDefaultIdentity<ApplicationUser>(options => { options.Stores.SchemaVersion = IdentitySchemaVersions.Version2; options.Stores.MaxLengthForKeys = 256; options.SignIn.RequireConfirmedAccount = false; })Risicobeperking: Om ervoor te zorgen dat de opties consistent worden toegepast, moet de applicatie worden ingesteld als opstartproject bij het uitvoeren van de EF-hulpprogramma's of, als alternatief,
IDesignTimeDbContextFactorymoet worden geïmplementeerd in het project datDbContextbevat.public class DatabaseContextDesignTimeFactory : IDesignTimeDbContextFactory<DatabaseContext> { public DatabaseContext CreateDbContext(string[] args) { var services = new ServiceCollection(); AddIdentity(services); var serviceProvider = services.BuildServiceProvider(); var optionsBuilder = new DbContextOptionsBuilder<DatabaseContext>(); optionsBuilder.UseApplicationServiceProvider(serviceProvider); optionsBuilder.UseSqlServer(); return new DatabaseContext(optionsBuilder.Options); } public static IServiceCollection AddIdentity(IServiceCollection services) { services.AddDefaultIdentity<ApplicationUser>(options => { options.Stores.SchemaVersion = IdentitySchemaVersions.Version2; options.Stores.MaxLengthForKeys = 256; options.SignIn.RequireConfirmedAccount = false; }) .AddRoles<IdentityRole>() .AddEntityFrameworkStores<DatabaseContext>(); return services; } }
Als uw scenario niet onder een van de bovenstaande gevallen valt en wanneer u een nieuwe migratie toevoegt, wordt elke keer dezelfde migratie of een lege migratie gemaakt en wordt de uitzondering nog steeds gegenereerd, maakt u een klein project voor opnieuw maken en het met het EF-team delen in een nieuw probleem.
Er wordt een uitzondering gegenereerd bij het toepassen van migraties in een expliciete transactie
Oud gedrag
Voor het flexibel toepassen van migraties is het volgende patroon vaak gebruikt:
await dbContext.Database.CreateExecutionStrategy().ExecuteAsync(async () =>
{
await using var transaction = await dbContext.Database.BeginTransactionAsync(cancellationToken);
await dbContext.Database.MigrateAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
});
Nieuw gedrag
Vanaf EF Core 9.0 starten Migrate- en MigrateAsync-aanroepen een transactie en voeren de opdrachten uit met behulp van een ExecutionStrategy en als uw app het bovenstaande patroon gebruikt, wordt er een uitzondering gegenereerd:
Er is een fout gegenereerd voor waarschuwing 'Microsoft. EntityFrameworkCore.Migrations.MigrationsUserTransactionWarning': er is een transactie gestart voordat migraties worden toegepast. Dit voorkomt dat een databasevergrendeling wordt verkregen en daarom wordt de database niet beschermd tegen gelijktijdige migratietoepassingen. De transacties en uitvoeringsstrategie worden indien nodig al beheerd door EF. Verwijder de externe transactie. Deze uitzondering kan worden onderdrukt of geregistreerd door gebeurtenis-id 'RelationalEventId.MigrationsUserTransactionWarning' door te geven aan de methode ConfigureWarnings in DbContext.OnConfiguring of AddDbContext.
Waarom
Als u een expliciete transactie gebruikt, voorkomt u dat een databasevergrendeling wordt verkregen en wordt de database daarom niet beschermd tegen gelijktijdige migratietoepassingen, maar wordt ook EF beperkt over hoe de transacties intern kunnen worden beheerd.
Maatregelen
Als er slechts één database-aanroep binnen de transactie is, verwijdert u de externe transactie en ExecutionStrategy:
await dbContext.Database.MigrateAsync(cancellationToken);
Als voor uw scenario een expliciete transactie is vereist en u een ander mechanisme hebt om gelijktijdige migratietoepassing te voorkomen, negeert u de waarschuwing:
options.ConfigureWarnings(w => w.Ignore(RelationalEventId.MigrationsUserTransactionWarning))
Wijzigingen met gemiddelde impact
Microsoft.EntityFrameworkCore.Design niet gevonden bij het gebruik van EF tools
Oud gedrag
Vroeger moesten de EF-hulpprogramma's op de volgende manier worden aangeroepen.
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="*.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Nieuw gedrag
Vanaf .NET SDK 9.0.200 wordt er een uitzondering gegenereerd wanneer een EF-hulpprogramma wordt aangeroepen:
Kan bestand of assembly 'Microsoft.EntityFrameworkCore.Design, Culture=neutral, PublicKeyToken=null' niet laden. Het systeem kan het opgegeven bestand niet vinden.
Waarom
EF-hulpprogramma's waren afhankelijk van een niet-gedocumenteerd gedrag van .NET SDK waardoor privéassets werden opgenomen in het gegenereerde bestand .deps.json. Dit is opgelost in sdk#45259. Helaas voldoet de EF-wijziging om hiervoor rekening te houden niet aan de onderhoudsbalk voor EF 9.0.x, dus deze wordt opgelost in EF 10.
Maatregelen
Als tijdelijke oplossing kunt u, voordat EF 10 wordt uitgebracht, de referentie van de Design assembly als publiceerbaar markeren.
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<Publish>true</Publish>
</PackageReference>
Dit wordt opgenomen in het gegenereerde bestand .deps.json, maar heeft een neveneffect van het kopiëren van Microsoft.EntityFrameworkCore.Design.dll naar de uitvoer en het publiceren van mappen.
Wijzigingen met lage impact
EF.Functions.Unhex() geeft nu byte[]? terug
Oud gedrag
De EF.Functions.Unhex() functie is eerder geannoteerd om byte[]te retourneren.
Nieuw gedrag
Vanaf EF Core 9.0 wordt Unhex() nu geannoteerd om byte[]?te retourneren.
Waarom
Unhex() wordt omgezet in de functie SQLite unhex, die NULL retourneert voor ongeldige invoer. Als gevolg hiervan heeft Unhex()null geretourneerd voor die gevallen, in strijd met de annotatie.
Maatregelen
Als u zeker weet dat de tekstinhoud die wordt doorgegeven aan Unhex() een geldige hexadecimale tekenreeks vertegenwoordigt, kunt u de operator null-forgiving toevoegen als een verklaring dat de aanroep nooit null retourneert:
var binaryData = await context.Blogs.Select(b => EF.Functions.Unhex(b.HexString)!).ToListAsync();
Voeg anders runtimecontroles toe voor null op de retourwaarde van Unhex().
Gecompileerde modellen verwijzen nu rechtstreeks naar waardeconvertermethoden
Oud gedrag
Voorheen zou EF bij het gebruik van waardeconversieprogramma's met gecompileerde modellen (met behulp van dotnet ef dbcontext optimize) verwijzen naar het type conversieprogramma en werkte alles correct.
public sealed class BooleanToCharConverter() : ValueConverter<bool, char>(v => ConvertToChar(v), v => ConvertToBoolean(v))
{
public static readonly BooleanToCharConverter Default = new();
private static char ConvertToChar(bool value) // Private method
=> value ? 'Y' : 'N';
private static bool ConvertToBoolean(char value) // Private method
=> value == 'Y';
}
Nieuw gedrag
Vanaf EF Core 9.0 genereert EF code die rechtstreeks verwijst naar de conversiemethoden zelf. Als deze methoden privé zijn, mislukt de compilatie.
Waarom
Deze wijziging was nodig om NativeAOT te ondersteunen.
Maatregelen
Maak de methoden waarnaar wordt verwezen door waardeconversieprogramma's openbaar of intern in plaats van privé.
De ariteit van nullability-argumenten van SqlFunctionExpression is gevalideerd.
Oud gedrag
Eerder was het mogelijk om een SqlFunctionExpression te maken met een ander aantal argumenten en argumenten voor null-propagatie.
Nieuw gedrag
Vanaf EF Core 9.0 wordt EF nu gegooid als het aantal argumenten en de doorgifteargumenten voor null-baarheid niet overeenkomen.
Waarom
Het niet overeenkomende aantal argumenten en argumenten voor het doorgeven van null-waarden kan leiden tot onverwacht gedrag.
Maatregelen
Zorg ervoor dat de argumentsPropagateNullability hetzelfde aantal elementen heeft als de arguments. Wanneer je twijfelt, gebruik false voor een null-argument.
ToString() methode retourneert nu een lege tekenreeks voor null exemplaren
Oud gedrag
Voorheen gaf EF inconsistente resultaten voor de methode ToString() wanneer de argumentwaarde nullwas. Bijvoorbeeld: ToString() op de eigenschap bool? met waarde null retourneerde null, maar voor uitdrukkingen zonder eigenschap bool?, waarvan de waarde null was, retourneerde het True. Het gedrag was ook inconsistent voor andere datatypen, bijvoorbeeld ToString() op null waarde-enum gaf een lege tekenreeks terug.
Nieuw gedrag
Vanaf EF Core 9.0 retourneert de ToString() methode nu in alle gevallen een lege tekenreeks wanneer de argumentwaarde wordt null.
Waarom
Het oude gedrag was inconsistent in verschillende gegevenstypen en situaties, en is niet afgestemd op het C#-gedrag.
Maatregelen
Als u wilt terugkeren naar het oude gedrag, moet u de query dienovereenkomstig herschrijven:
var newBehavior = context.Entity.Select(x => x.NullableBool.ToString());
var oldBehavior = context.Entity.Select(x => x.NullableBool == null ? null : x.NullableBool.ToString());
Gedeelde frameworkafhankelijkheden zijn bijgewerkt naar 9.0.x
Oud gedrag
Apps die gebruikmaken van de Microsoft.NET.Sdk.Web SDK en het targetten van net8.0, zullen pakketten zoals System.Text.Json, Microsoft.Extensions.Caching.Memory, Microsoft.Extensions.Configuration.Abstractions, Microsoft.Extensions.Logging en Microsoft.Extensions.DependencyModel uit het gedeelde framework halen, zodat deze assembly's normaal gesproken niet met de app worden geïmplementeerd.
Nieuw gedrag
Ef Core 9.0 ondersteunt nog steeds net8.0, maar verwijst nu naar de 9.0.x-versies van System.Text.Json, Microsoft.Extensions.Caching.Memory, Microsoft.Extensions.Configuration.Abstractions, Microsoft.Extensions.Logging en Microsoft.Extensions.DependencyModel. Apps die zijn gericht op net8.0, kunnen niet gebruikmaken van het gedeelde framework om te voorkomen dat deze assembly's worden geïmplementeerd.
Waarom
De overeenkomende afhankelijkheidsversies bevatten de nieuwste beveiligingsoplossingen en het gebruik ervan vereenvoudigt het onderhoudsmodel voor EF Core.
Maatregelen
Wijzig uw app om deze te richten op net9.0 om het vorige gedrag te herstellen.
EF-hulpprogramma's bieden geen ondersteuning meer voor .NET Framework-projecten
Oud gedrag
Voorheen werkten de EF Core-hulpprogramma's (dotnet-ef CLI en Package Manager Console) samen met projecten die gericht zijn op .NET Framework.
Nieuw gedrag
Vanaf EF Core 9.0 werken de EF Core-hulpprogramma's niet meer met projecten die zijn gericht op .NET Framework. De hulpprogramma's produceren een fout wanneer het opstartproject is gericht op .NET Framework.
Waarom
De huidige versie van EF Core-hulpprogramma's werkt met alle ondersteunde EF Core-versies en er zijn geen ondersteunde EF Core-versies meer die op .NET Framework werken.
Maatregelen
Werk uw project bij naar .NET (bijvoorbeeld .NET 8 of hoger). Als uw project momenteel is gericht op .NET Framework, raadpleegt u de handleiding porteren voor informatie over het migreren naar .NET.
EF.Constant() en EF.Parameter() werkt niet meer binnen gecompileerde query's
Oud gedrag
In EF Core 8 Constant en Parameter kan worden gebruikt binnen gecompileerde query's (CompileQuery en CompileAsyncQuery):
var lookbackDays = 7;
var compiledQuery = EF.CompileAsyncQuery(
(AppDbContext db) => db.Blogs
.Where(b => b.PublishedOn >= DateTime.Today.AddDays(EF.Constant(-lookbackDays))));
Nieuw gedrag
Vanaf EF Core 9.0 genereert het gebruik Constant of Parameter binnen een gecompileerde query een InvalidCastException:
Unable to cast object of type 'System.Linq.Expressions.ConstantExpression' to type 'System.Linq.Expressions.ParameterExpression'.
Waarom
De interne implementatie van Constant is gewijzigd om volledige querycompilatie te voorkomen voor elke verschillende constante waarde. De vorige implementatie introduceerde constanten knooppunten vroegtijdig in de querypijplijn (vóór het query-caching), waardoor dure cachemissers werden veroorzaakt wanneer een andere waarde werd doorgegeven aan EF.Constant(). De nieuwe implementatie verwerkt deze methoden in een later stadium, wat niet compatibel is met gecompileerde query's.
Maatregelen
Verwijder ofwel de aanroep Constant of Parameter uit de gecompileerde query, of stop met het gebruik van een gecompileerde query voor die specifieke query. Houd er rekening mee dat het verwijderen van EF.Constant() ertoe leidt dat de waarde wordt verzonden als een SQL-parameter in plaats van als een constante geïnlineerd, wat de prestaties van het queryplan kan beïnvloeden.
Ingrijpende wijzigingen in Azure Cosmos DB
Er is uitgebreid werk gedaan om de Azure Cosmos DB provider in 9.0 beter te maken. De wijzigingen bevatten een aantal belangrijke wijzigingen die van grote invloed zijn; Lees het volgende zorgvuldig als u een upgrade uitvoert van een bestaande toepassing.
| wijziging die fouten veroorzaken | impact |
|---|---|
De discriminatoreigenschap heet nu $type in plaats van Discriminator |
Hoog |
De eigenschap id bevat standaard de discriminator niet meer |
Hoog |
De eigenschap JSON-id is toegewezen aan de sleutel |
Hoog |
| Sync I/O via de Azure Cosmos DB-provider wordt niet meer ondersteund | Gemiddeld |
| SQL-query's moeten nu JSON-waarden rechtstreeks projecteren | Gemiddeld |
| Ongedefinieerde resultaten worden nu automatisch gefilterd uit queryresultaten | Gemiddeld |
| onjuist vertaalde query's worden niet meer vertaald | Gemiddeld |
HasIndex gooit nu in plaats van te worden genegeerd |
Laag |
IncludeRootDiscriminatorInJsonId hernoemd naar HasRootDiscriminatorInJsonId |
Laag |
| De versie waarnaar newtonsoft.Json wordt verwezen, is bijgewerkt van 10.0.2 naar 13.0.1 | Laag |
Wijzigingen met hoge impact
De discriminatoreigenschap heet nu $type in plaats van Discriminator
Oud gedrag
EF voegt automatisch een discriminatoreigenschap toe aan JSON-documenten om het entiteitstype te identificeren dat het document vertegenwoordigt. In eerdere versies van EF werd deze JSON-eigenschap standaard Discriminator genoemd.
Nieuw gedrag
Vanaf EF Core 9.0 wordt de discriminatoreigenschap nu standaard $type genoemd. Als u bestaande documenten in Azure Cosmos DB van eerdere versies van EF hebt, gebruiken deze de oude Discriminator naamgeving en na een upgrade naar EF 9.0 mislukken query's op deze documenten.
Waarom
Een opkomende JSON-praktijk maakt gebruik van een $type eigenschap in scenario's waarin het type van een document moet worden geïdentificeerd. System.Text.Json van .NET ondersteunt bijvoorbeeld ook polymorfisme, waarbij $type wordt gebruikt als standaarddiscriminatieeigenschapsnaam (docs). De standaardwaarde is gewijzigd om te worden afgestemd op de rest van het ecosysteem en het gemakkelijker te maken om te werken met externe hulpprogramma's.
Maatregelen
De eenvoudigste oplossing is om gewoon de naam van de discriminator-eigenschap te configureren als Discriminator, net zoals vóór het gebruik van HasDiscriminator.
modelBuilder.Entity<Session>().HasDiscriminator<string>("Discriminator");
Als u dit doet voor al uw entiteitstypen op het hoogste niveau, gedraagt EF zich net als voorheen.
Op dit moment kunt u desgewenst ook al uw documenten bijwerken om de nieuwe $type naamgeving te gebruiken.
De eigenschap id bevat nu standaard alleen de eigenschap EF-sleutel
Oud gedrag
Voorheen heeft EF de discriminatorwaarde van uw entiteitstype ingevoegd in de eigenschap id van het document. Als u bijvoorbeeld een Blog entiteitstype hebt opgeslagen met een eigenschap Id met 8, bevat de eigenschap JSON idBlog|8.
Nieuw gedrag
Vanaf EF Core 9.0 bevat de eigenschap JSON id niet langer de discriminatorwaarde en bevat deze alleen de waarde van uw sleuteleigenschap. In het bovenstaande voorbeeld is de eigenschap JSON id gewoon 8. Als u bestaande documenten in Azure Cosmos DB uit eerdere versies van EF hebt, hebben deze de discriminatorwaarde in de eigenschap JSON id en na een upgrade naar EF 9.0 mislukken query's op deze documenten.
Waarom
Omdat de eigenschap JSON-id uniek moet zijn, is de discriminator er eerder aan toegevoegd om verschillende entiteiten met dezelfde sleutelwaarde toe te staan. Het was bijvoorbeeld mogelijk om zowel een Blog als een Post te hebben, met een eigenschap Id die de waarde 8 bevat in dezelfde container en partitie. Dit is beter afgestemd op relationele databasegegevensmodelleringspatronen, waarbij elk entiteitstype wordt toegewezen aan een eigen tabel en daarom een eigen sleutelruimte heeft.
EF 9.0 heeft de mapping over het algemeen gewijzigd om beter aan te sluiten bij de gebruikelijke Azure Cosmos DB NoSQL praktijken en verwachtingen, in plaats van aan de verwachtingen van gebruikers uit relationele databases te voldoen. Bovendien maakt het met de discrimorwaarde in de eigenschap id het moeilijker voor externe hulpprogramma's en systemen om te communiceren met door EF gegenereerde JSON-documenten; dergelijke externe systemen zijn over het algemeen niet op de hoogte van de EF-discriminatorwaarden, die standaard zijn afgeleid van .NET typen.
Maatregelen
De eenvoudigste oplossing is om EF te configureren voor het opnemen van de discriminator in de JSON-eigenschap id, zoals voorheen met HasDiscriminatorInJsonId. Er is voor dit doel een nieuwe configuratieoptie geïntroduceerd:
modelBuilder.Entity<Session>().HasDiscriminatorInJsonId();
Als u dit doet voor al uw entiteitstypen op het hoogste niveau, gedraagt EF zich net als voorheen.
Op dit moment kunt u, indien gewenst, ook al uw documenten bijwerken om hun JSON-id-eigenschap opnieuw te schrijven. Houd er rekening mee dat dit alleen mogelijk is als entiteiten van verschillende typen niet dezelfde id-waarde binnen dezelfde container delen.
De eigenschap JSON id is toegewezen aan de sleutel
Oud gedrag
Eerder heeft EF een schaduweigenschap gemaakt die is toegewezen aan de eigenschap JSON id, tenzij een van de eigenschappen expliciet is toegewezen aan id.
Nieuw gedrag
Vanaf EF Core 9 wordt de sleuteleigenschap, indien mogelijk, toegewezen aan de JSON-id eigenschap. Dit betekent dat de sleuteleigenschap niet langer wordt bewaard in het document onder een andere naam met dezelfde waarde, zodat niet-EF-code die de documenten verbruikt en erop vertrouwt dat deze eigenschap aanwezig is, niet meer goed werkt.
Waarom
EF 9.0 heeft de mapping algemeen gewijzigd om beter aan te sluiten bij de gangbare Azure Cosmos DB NoSQL-praktijken en -verwachtingen. En het is niet gebruikelijk om de sleutelwaarde tweemaal in het document op te slaan.
Maatregelen
Als u het gedrag van EF Core 8 wilt behouden, is de eenvoudigste oplossing om te gebruiken HasShadowId, een nieuwe configuratieoptie die voor dit doel is geïntroduceerd:
modelBuilder.Entity<Session>().HasShadowId();
Als u dit doet voor al uw entiteitstypen op het hoogste niveau, gedraagt EF zich net als voorheen. U kunt deze ook toepassen op alle entiteitstypen in het model met één aanroep met behulp van HasShadowIds:
modelBuilder.HasShadowIds();
Wijzigingen met gemiddelde impact
I/O synchroniseren via de Azure Cosmos DB-provider wordt niet meer ondersteund
Oud gedrag
Voorheen zouden synchrone methoden zoals ToList of SaveChanges ertoe leiden dat EF Core synchroon blokkeert met behulp van .GetAwaiter().GetResult() bij het uitvoeren van asynchrone aanroepen met de Azure Cosmos DB SDK. Dit kan leiden tot een impasse.
Nieuw gedrag
Vanaf EF Core 9.0 wordt EF nu standaard uitgevoerd wanneer wordt geprobeerd synchrone I/O te gebruiken. Het uitzonderingsbericht is 'Azure Cosmos DB biedt geen ondersteuning voor synchrone I/O. Zorg ervoor dat u alleen asynchrone methoden gebruikt en wacht alleen op asynchrone methoden wanneer u Entity Framework Core gebruikt voor toegang tot Azure Cosmos DB. Zie https://aka.ms/ef-cosmos-nosync voor meer informatie.
Waarom
Synchrone blokkering op asynchrone methoden kan leiden tot deadlocks en de SDK van Azure Cosmos DB ondersteunt alleen asynchrone methoden.
Maatregelen
In EF Core 9.0 kan de fout worden onderdrukt met:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.ConfigureWarnings(w => w.Ignore(CosmosEventId.SyncNotSupported));
}
Dat gezegd hebbende, moeten toepassingen stoppen met het gebruik van synchronisatie-API's met Azure Cosmos DB, omdat dit niet wordt ondersteund door de Azure Cosmos DB SDK. De mogelijkheid om de uitzondering te onderdrukken, wordt verwijderd in een toekomstige release van EF Core, waarna de enige optie is om asynchrone API's te gebruiken.
SQL-query's moeten nu JSON-waarden rechtstreeks projecteren
Oud gedrag
Eerder gegenereerde EF-query's zoals de volgende:
SELECT c["City"] FROM root c
Dergelijke query's zorgen ervoor dat Azure Cosmos DB elk resultaat in een JSON-object verpakt, als volgt:
[
{
"City": "Berlin"
},
{
"City": "México D.F."
}
]
Nieuw gedrag
Vanaf EF Core 9.0 voegt EF nu de VALUE modifier als volgt toe aan query's:
SELECT VALUE c["City"] FROM root c
Dergelijke query's zorgen ervoor dat Azure Cosmos DB de waarden rechtstreeks retourneert, zonder dat ze worden verpakt:
[
"Berlin",
"México D.F."
]
Als uw toepassing gebruikmaakt van SQL-query's, worden dergelijke query's waarschijnlijk verbroken na een upgrade naar EF 9.0, omdat ze de VALUE modifier niet bevatten.
Waarom
Het verpakken van elk resultaat in een extra JSON-object kan leiden tot prestatievermindering in sommige scenario's, bloats de nettolading van het JSON-resultaat en is niet de natuurlijke manier om met Azure Cosmos DB te werken.
Maatregelen
Als u dit wilt beperken, voegt u de VALUE modifier toe aan de projecties van uw SQL-query's, zoals hierboven wordt weergegeven.
Ongedefinieerde resultaten worden nu automatisch gefilterd uit de queryresultaten.
Oud gedrag
Eerder gegenereerde EF-query's zoals de volgende:
SELECT c["City"] FROM root c
Dergelijke query's zorgen ervoor dat Azure Cosmos DB elk resultaat in een JSON-object verpakt, als volgt:
[
{
"City": "Berlin"
},
{
"City": "México D.F."
}
]
Als een van de resultaten niet is gedefinieerd (bijvoorbeeld de eigenschap City niet aanwezig was in het document), werd er een leeg document geretourneerd en zou EF null voor dat resultaat retourneren.
Nieuw gedrag
Vanaf EF Core 9.0 voegt EF nu de VALUE modifier als volgt toe aan query's:
SELECT VALUE c["City"] FROM root c
Dergelijke query's zorgen ervoor dat Azure Cosmos DB de waarden rechtstreeks retourneert, zonder dat ze worden verpakt:
[
"Berlin",
"México D.F."
]
Het Azure Cosmos DB gedrag is om automatisch undefined waarden uit de resultaten te filteren. Dit betekent dat als een van de eigenschappen City niet aanwezig is in het document, de query slechts één resultaat retourneert, in plaats van twee resultaten, waarbij één null.
Waarom
Het verpakken van elk resultaat in een extra JSON-object kan leiden tot prestatievermindering in sommige scenario's, bloats de nettolading van het JSON-resultaat en is niet de natuurlijke manier om met Azure Cosmos DB te werken.
Maatregelen
Als het belangrijk is voor uw toepassing om null-waarden te verkrijgen voor niet-gedefinieerde resultaten, verbind dan de undefined-waarden tot null met behulp van de nieuwe EF.Functions.Coalesce-operator.
var users = await context.Customer
.Select(c => EF.Functions.CoalesceUndefined(c.City, null))
.ToListAsync();
Onjuist vertaalde query's worden niet meer vertaald
Oud gedrag
Eerder vertaalde EF vragen zoals deze:
var sessions = await context.Sessions
.Take(5)
.Where(s => s.Name.StartsWith("f"))
.ToListAsync();
De SQL-vertaling voor deze query is echter onjuist:
SELECT c
FROM root c
WHERE ((c["Discriminator"] = "Session") AND STARTSWITH(c["Name"], "f"))
OFFSET 0 LIMIT @__p_0
In SQL wordt de WHERE-component geëvalueerd voordat de OFFSET- en LIMIT-componenten; maar in de bovenstaande LINQ-query wordt de operator Take weergegeven vóór de operator Where. Als gevolg hiervan kunnen dergelijke query's onjuiste resultaten retourneren.
Nieuw gedrag
Vanaf EF Core 9.0 worden dergelijke query's niet meer vertaald en wordt er een uitzondering gegenereerd.
Waarom
Onjuiste vertalingen kunnen leiden tot beschadiging van gegevens op de achtergrond, wat kan leiden tot moeilijk te detecteren fouten in uw toepassing. EF geeft altijd de voorkeur aan een fail-fast aanpak door vroegtijdig fouten op te werpen, in plaats van mogelijk gegevenscorruptie te veroorzaken.
Maatregelen
Als u tevreden bent met het vorige gedrag en dezelfde SQL wilt uitvoeren, wisselt u gewoon de volgorde van LINQ-operators om:
var sessions = await context.Sessions
.Where(s => s.Name.StartsWith("f"))
.Take(5)
.ToListAsync();
Helaas biedt Azure Cosmos DB momenteel geen ondersteuning voor de component OFFSET en LIMIT in SQL-subquery's. Dit is wat de juiste vertaling van de oorspronkelijke LINQ-query vereist.
Wijzigingen met lage impact
HasIndex gooit nu in plaats van genegeerd te worden
Oud gedrag
Voorheen werden aanroepen naar HasIndex genegeerd door de EF Cosmos DB-provider.
Nieuw gedrag
De provider genereert nu als HasIndex is opgegeven.
Waarom
In Azure Cosmos DB worden alle eigenschappen standaard geïndexeerd en hoeft er geen indexering te worden opgegeven. Hoewel het mogelijk is om een aangepast indexeringsbeleid te definiëren, wordt dit momenteel niet ondersteund door EF en kan dit worden gedaan via de Azure Portal zonder EF-ondersteuning. Omdat HasIndex oproepen niets uitrichtten, zijn ze niet langer toegestaan.
Maatregelen
Verwijder alle aanroepen naar HasIndex.
IncludeRootDiscriminatorInJsonId werd hernoemd naar HasRootDiscriminatorInJsonId na de release van 9.0.0-rc.2
Oud gedrag
De IncludeRootDiscriminatorInJsonId API is geïntroduceerd in 9.0.0 rc.1.
Nieuw gedrag
Voor de definitieve release van EF Core 9.0 is de naam van de API gewijzigd in HasRootDiscriminatorInJsonId
Waarom
Een andere gerelateerde API is hernoemd om te beginnen met Has in plaats van Include, en dus is deze ook hernoemd voor consistentie.
Maatregelen
Als uw code gebruikmaakt van de IncludeRootDiscriminatorInJsonId-API, verander dit naar HasRootDiscriminatorInJsonId.
De versie waarnaar newtonsoft.Json wordt verwezen, is bijgewerkt van 10.0.2 naar 13.0.1
Oud gedrag
De Cosmos-provider verwijst naar Newtonsoft.Json versie 10.0.2.
Nieuw gedrag
Vanaf EF Core 9.0 verwijst de Cosmos-provider naar Newtonsoft.Json versie 13.0.1.
Waarom
De eerder gebruikte versie van Newtonsoft.Json heeft bekende beveiligingsproblemen. De versie is bijgewerkt om te voorkomen dat deze afhankelijk is van een pakketversie met bekende beveiligingsproblemen.
Maatregelen
De upgrade naar Newtonsoft.Json 13.0.1 mag in de meeste gevallen geen problemen veroorzaken. Als uw toepassing Newtonsoft.Json rechtstreeks gebruikt en afhankelijk is van een specifieke oudere versie, kunt u uw toepassing bijwerken zodat deze compatibel is met Newtonsoft.Json 13.0.1 of hoger. Zie de opmerkingen bij de release van Newtonsoft.Json voor meer informatie over wijzigingen tussen versies.