Breaking Changes in EF Core 9 (EF9)
Auf dieser Seite werden API-Änderungen und Behavior Changes dokumentiert, die bei einem Update von EF Core 8 auf EF Core 9 zu Problemen mit bestehenden Anwendungen führen können. Überprüfen Sie frühere grundlegende Änderungen, wenn sie von einer früheren Version von EF Core aktualisiert werden:
Zielframework
EF Core 9 zielt auf .NET 8 ab. Dies bedeutet, dass vorhandene Anwendungen, die auf .NET 8 abzielen, dies weiterhin tun können. Anwendungen für ältere .NET-, .NET Core- und .NET Framework-Versionen müssen .NET 8 oder .NET 9 für die Verwendung von EF Core 9 verwenden.
Zusammenfassung
Hinweis
Wenn Sie Azure Cosmos DB verwenden, lesen Sie den separaten Abschnitt unten zu Azure Cosmos DB-Änderungen.
Änderungen mit hoher Auswirkung
Eine Ausnahme wird ausgelöst, wenn Migrationen angewendet werden und ausstehende Modelländerungen vorhanden sind.
Nachverfolgung von Issue #33732
Altes Verhalten
Wenn das Modell im Vergleich zur letzten Migration ausstehende Änderungen aufweist, werden sie nicht mit den restlichen Migrationen angewendet, wenn Migrate
aufgerufen wird.
Neues Verhalten
Ab EF Core 9.0 wird eine Ausnahme ausgelöst, wenn das Modell im Vergleich zur letzten Migration ausstehende Änderungen aufweist und dotnet ef database update
, Migrate
oder MigrateAsync
aufgerufen wird.
Das Modell für den Kontext „DbContext“ hat ausstehende Änderungen. Fügen Sie eine neue Migration hinzu, bevor Sie die Datenbank aktualisieren. Diese Ausnahme lässt sich unterdrücken oder protokollieren, indem Sie die Ereignis-ID „RelationalEventId.PendingModelChangesWarning“ an die Methode „ConfigureWarnings“ in „DbContext.OnConfiguring“ oder „AddDbContext“ übergeben.
Warum?
Nach Modelländerungen zu vergessen, eine neue Migration hinzuzufügen, ist ein häufiger Fehler, der in einigen Fällen schwer zu diagnostizieren sein kann. Die neue Ausnahme stellt sicher, dass das Modell der App der Datenbank entspricht, nachdem die Migrationen angewendet wurden.
Gegenmaßnahmen
Es gibt mehrere häufige Situationen, in denen diese Ausnahme ausgelöst werden kann:
- Es gibt überhaupt keine Migrationen. Dies ist üblich, wenn die Datenbank auf andere Wege aktualisiert wird.
- Risikominderung: Wenn Sie keine Migrationen für die Verwaltung des Datenbankschemas verwenden möchten, entfernen Sie den
Migrate
- oderMigrateAsync
-Aufruf, andernfalls fügen Sie eine Migration hinzu.
- Risikominderung: Wenn Sie keine Migrationen für die Verwaltung des Datenbankschemas verwenden möchten, entfernen Sie den
- Es gibt mindestens eine Migration, aber der Modellschnappschuss fehlt. Dies ist üblich für manuell erstellte Migrationen.
- Risikominderung: Fügen Sie eine neue Migration mithilfe von EF-Tools hinzu. Dadurch wird die Modellmomentaufnahme aktualisiert.
- Das Modell wurde vom Entwickler nicht geändert, aber es ist in einer nicht deterministischen Weise integriert, die dazu führt, dass EF sie als geändert erkennt. Dies ist üblich, wenn
new DateTime()
,DateTime.Now
,DateTime.UtcNow
oderGuid.NewGuid()
in Objekten verwendet werden, die anHasData()
bereitgestellt werden.- Risikominderung: Fügen Sie eine neue Migration hinzu, überprüfen Sie deren Inhalt, um die Ursache zu finden, und ersetzen Sie die dynamischen Daten durch einen statischen, hartcodierten Wert im Modell. Die Migration sollte neu erstellt werden, nachdem das Modell korrigiert wurde. Wenn dynamische Daten für das Seeding verwendet werden müssen, sollten Sie das neue Seedingmuster anstelle von
HasData()
verwenden.
- Risikominderung: Fügen Sie eine neue Migration hinzu, überprüfen Sie deren Inhalt, um die Ursache zu finden, und ersetzen Sie die dynamischen Daten durch einen statischen, hartcodierten Wert im Modell. Die Migration sollte neu erstellt werden, nachdem das Modell korrigiert wurde. Wenn dynamische Daten für das Seeding verwendet werden müssen, sollten Sie das neue Seedingmuster anstelle von
- Die letzte Migration wurde für einen anderen Anbieter erstellt als der, der zum Anwenden der Migrationen verwendet wurde.
- Risikominderung: Dies ist ein Szenario, das nicht unterstützt wird. Die Warnung kann mithilfe des folgenden Codeausschnitts unterdrückt werden, dieses Szenario funktioniert jedoch wahrscheinlich nicht mehr in einer zukünftigen EF Core-Release. Die empfohlene Lösung ist , um einen separaten Satz von Migrationen für jeden Anbieter zu generieren.
- Die Migrationen werden dynamisch ausgewählt oder generiert, indem bestimmte EF-Dienste ersetzt werden.
Risikominderung: Die Warnung ist in diesem Fall ein Fehlalarm und sollte unterdrückt werden.
options.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning))
Wenn Ihr Szenario zu keinem der oben genannten Fälle passt und das Hinzufügen einer neuen Migration jedes Mal die gleiche Migration oder eine leere Migration erstellt und die Ausnahme weiterhin ausgelöst wird, erstellen Sie ein kleines Repro-Projekt und geben sie es dem EF-Team in einem neuen Problem weiter.
Eine Ausnahme wird ausgelöst, wenn Migrationen in einer expliziten Transaktion angewendet werden.
Nachverfolgung von Issue 17578
Altes Verhalten
Um Migrationen robust anzuwenden, wurde häufig das folgende Muster verwendet:
await dbContext.Database.CreateExecutionStrategy().ExecuteAsync(async () =>
{
await using var transaction = await dbContext.Database.BeginTransactionAsync(cancellationToken);
await dbContext.Database.MigrateAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
});
Neues Verhalten
Ab EF Core 9.0 starten Migrate
- und MigrateAsync
-Aufrufe eine Transaktion und führen die Befehle mithilfe einer ExecutionStrategy
aus, und wenn ihre App das obige Muster verwendet, wird eine Ausnahme ausgelöst:
Es wurde ein Fehler für die Warnung „Microsoft.EntityFrameworkCore.Migrations.MigrationsUserTransactionWarning“ generiert: Eine Transaktion wurde vor dem Anwenden von Migrationen gestartet. Dadurch wird verhindert, dass eine Datenbanksperre erworben wird, und daher wird die Datenbank nicht vor gleichzeitig ausgeführten Migrationsanwendungen geschützt. Die Transaktionen und die Ausführungsstrategie werden bereits wie erforderlich von EF verwaltet. Entfernen Sie die externe Transaktion. Diese Ausnahme kann unterdrückt oder protokolliert werden, indem die Ereignis-ID „RelationalEventId.MigrationsUserTransactionWarning“ an die Methode „ConfigureWarnings“ in „DbContext.OnConfiguring“ oder „AddDbContext“ übergeben wird.
Warum?
Eine explizite Transaktion verhindert, dass eine Datenbanksperre erworben wird. Daher bleibt die Datenbank nicht vor gleichzeitigen Migrationsanwendungen geschützt. Außerdem schränkt dies EF in der Art und Weise ein, wie es die Transaktionen intern verwalten kann.
Gegenmaßnahmen
Wenn nur ein Datenbankaufruf innerhalb der Transaktion vorhanden ist, entfernen Sie die externe Transaktion und ExecutionStrategy
:
await dbContext.Database.MigrateAsync(cancellationToken);
Andernfalls, wenn Ihr Szenario eine explizite Transaktion erfordert und Sie einen anderen Mechanismus zum Verhindern der gleichzeitigen Migrationsanwendung haben, ignorieren Sie die Warnung:
options.ConfigureWarnings(w => w.Ignore(RelationalEventId.MigrationsUserTransactionWarning))
Änderungen mit mittlerer Auswirkung
Microsoft.EntityFrameworkCore.Design
bei Verwendung von EF-Tools nicht gefunden
Nachverfolgung von Issue 35265
Altes Verhalten
Vorab erforderten die EF-Tools, dass Microsoft.EntityFrameworkCore.Design
wie folgt referenziert wird.
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="*.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Neues Verhalten
Ab .NET SDK 9.0.200 wird eine Ausnahme ausgelöst, wenn ein EF-Tool aufgerufen wird:
Datei oder Assembly 'Microsoft.EntityFrameworkCore.Design, Culture=neutral, PublicKeyToken=null' konnte nicht geladen werden. Die angegebene Datei wurde nicht gefunden.
Warum?
EF-Tools basieren auf einem nicht dokumentierten Verhalten des .NET SDK, das dazu führte, dass private Ressourcen in die generierte .deps.json
-Datei aufgenommen wurden. Dies wurde in sdk#45259 behoben. Leider erfüllt die EF-Änderung zur Berücksichtigung dessen nicht die Wartungsanforderungen für EF 9.0.x, sodass sie in EF 10 behoben wird.
Gegenmaßnahmen
Als Problemumgehung vor der Veröffentlichung von EF 10 können Sie den Design
-Assemblyverweis als veröffentlichungsfähig kennzeichnen:
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<Publish>true</Publish>
</PackageReference>
Dies schließt sie in die generierte .deps.json
-Datei ein, hat jedoch den Nebeneffekt, Microsoft.EntityFrameworkCore.Design.dll
in die Ausgabe- und Veröffentlichungsordner zu kopieren.
Änderungen mit geringer Auswirkung
EF.Functions.Unhex()
gibt jetzt byte[]?
zurück
Nachverfolgung von Issue 33864
Altes Verhalten
Die EF.Functions.Unhex()
Funktion wurde zuvor mit Anmerkungen versehen, um byte[]
zurückzugeben.
Neues Verhalten
Ab EF Core 9.0 wird Unhex() nun kommentiert, um byte[]?
zurückzugeben.
Warum?
Unhex()
wird in die SQLite-Funktion unhex
übersetzt, die bei ungültigen Eingaben NULL zurückgibt. Infolgedessen gab Unhex()
für diese Fälle null
zurück, was einen Verstoß gegen die Anmerkung darstellt.
Gegenmaßnahmen
Wenn Sie sicher sind, dass der an Unhex()
übergebene Textinhalt eine gültige hexadezimale Zeichenkette darstellt, können Sie einfach den Null-Forgiving-Operator als Zusicherung hinzufügen, dass der Aufruf niemals Null zurückgibt:
var binaryData = await context.Blogs.Select(b => EF.Functions.Unhex(b.HexString)!).ToListAsync();
Fügen Sie andernfalls Laufzeitüberprüfungen auf NULL für den Rückgabewert von Unhex() hinzu.
NULL-Zulässigkeitsargumente von SqlFunctionExpression
Nachverfolgung von Issue 33852
Altes Verhalten
Zuvor war es möglich, eine SqlFunctionExpression
mit einer anderen Anzahl von Argumenten und NULL-Zulässigkeitsverteilungsargumenten zu erstellen.
Neues Verhalten
Ab EF Core 9.0 löst EF jetzt aus, wenn die Anzahl von Argumenten und NULL-Zulässigkeitsverteilungsargumenten nicht übereinstimmen.
Warum?
Es kann zu unerwartetem Verhalten führen, dass keine übereinstimmende Anzahl von Argumenten und Verteilungsargumenten zur NULL-Zulässigkeit vorhanden sind.
Gegenmaßnahmen
Stellen Sie sicher, dass die argumentsPropagateNullability
dieselbe Anzahl von Elementen wie die arguments
aufweist. Verwenden Sie im Zweifelsfall false
für das NULL-Zulässigkeitsargument.
ToString()
-Methode gibt jetzt für null
-Instanzen eine leere Zeichenfolge zurück
Nachverfolgung von Issue 33941
Altes Verhalten
Zuvor wurden von EF inkonsistente Ergebnisse für die ToString()
-Methode zurückgegeben, wenn der Argumentwert null
war. So wurde beispielsweise bei ToString()
für die Eigenschaft bool?
mit dem Wert null
der Wert null
zurückgegeben, aber bei Ausdrücken ohne die Eigenschaft bool?
, deren Wert null
war, wurde True
zurückgegeben. Das Verhalten war auch für andere Datentypen inkonsistent. So wurde beispielsweise bei ToString()
für die null
-Wertenumeration eine leere Zeichenfolge zurückgegeben.
Neues Verhalten
Ab EF Core 9.0 gibt die Methode ToString()
nun konsistent in allen Fällen eine leere Zeichenfolge zurück, wenn der Argumentwert null
ist.
Warum?
Das alte Verhalten war bei unterschiedlichen Datentypen und in unterschiedlichen Situationen inkonsistent und nicht auf das Verhalten von C# abgestimmt.
Gegenmaßnahmen
Wenn Sie zum alten Verhalten zurückkehren möchten, schreiben Sie die Abfrage entsprechend um:
var newBehavior = context.Entity.Select(x => x.NullableBool.ToString());
var oldBehavior = context.Entity.Select(x => x.NullableBool == null ? null : x.NullableBool.ToString());
Abhängigkeiten des freigegebenen Frameworks wurden auf 9.0.x aktualisiert
Altes Verhalten
Apps, die das Microsoft.NET.Sdk.Web
SDK verwenden und für net8.0 konzipiert sind, lösen Pakete wie System.Text.Json
, Microsoft.Extensions.Caching.Memory
, Microsoft.Extensions.Configuration.Abstractions
, Microsoft.Extensions.Logging
und Microsoft.Extensions.DependencyModel
über das freigegebene Framework auf. Daher werden diese Assemblys normalerweise nicht zusammen mit der App bereitgestellt.
Neues Verhalten
EF Core 9.0 unterstützt zwar weiterhin net8.0, verweist nun aber auf die 9.0.x-Versionen von System.Text.Json
, Microsoft.Extensions.Caching.Memory
, Microsoft.Extensions.Configuration.Abstractions
, Microsoft.Extensions.Logging
und Microsoft.Extensions.DependencyModel
. Apps, die für net8.0 konzipiert sind, können das freigegebene Framework nicht nutzen, um die Bereitstellung dieser Assemblys zu vermeiden.
Warum?
Die entsprechenden Abhängigkeitsversionen enthalten die neuesten Sicherheitskorrekturen, und ihre Verwendung vereinfacht das Wartungsmodell für EF Core.
Gegenmaßnahmen
Richten Sie Ihre App auf net9.0 aus, um das vorherige Verhalten zu erhalten.
Breaking Changes für Azure Cosmos DB
Der Azure Cosmos DB-Anbieter wurde in der Version 9.0 durch zahlreiche Maßnahmen verbessert. Die Änderungen umfassen eine Reihe von Änderungen mit hoher Auswirkung; Wenn Sie ein Upgrade einer vorhandenen Anwendung durchführen, lesen Sie bitte Folgendes sorgfältig.
Änderungen mit hoher Auswirkung
Die Diskriminatoreigenschaft wird jetzt $type
anstelle von Discriminator
genannt
Altes Verhalten
EF fügt JSON-Dokumenten automatisch eine Diskriminatoreigenschaft hinzu, um den Entitätstyp zu identifizieren, den das Dokument darstellt. In früheren Versionen von EF wurde diese JSON-Eigenschaft standardmäßig Discriminator
genannt.
Neues Verhalten
Ab EF Core 9.0 wird die Diskriminatoreigenschaft jetzt standardmäßig $type
genannt. Falls bei Ihnen in Azure Cosmos DB Dokumente aus früheren Versionen von EF vorhanden sind, verwenden diese die alte Benennung Discriminator
, und nach dem Upgrade auf EF 9.0 tritt bei Abfragen für diese Dokumente ein Fehler auf.
Warum?
Eine neue JSON-Praxis verwendet eine $type
Eigenschaft in Szenarien, in denen der Typ eines Dokuments identifiziert werden muss. System.Text.Json von .NET unterstützt zum Beispiel auch Polymorphismus, wobei $type
der Standardname der Diskriminatoreigenschaft (Docs) verwendet. Um den Rest des Ökosystems auszurichten und die Zusammenarbeit mit externen Tools zu vereinfachen, wurde die Standardeinstellung geändert.
Gegenmaßnahmen
Die einfachste Entschärfung besteht darin, einfach den Namen der Diskriminatoreigenschaft so Discriminator
zu konfigurieren, wie zuvor:
modelBuilder.Entity<Session>().HasDiscriminator<string>("Discriminator");
Dadurch verhält sich EF für alle Entitätstypen auf oberster Ebene genau wie zuvor.
Wenn Sie möchten, können Sie auch alle Ihre Dokumente so aktualisieren, dass sie die neue $type
Benennung verwenden.
Die id
Eigenschaft enthält jetzt standardmäßig nur die EF-Schlüsseleigenschaft.
Altes Verhalten
Zuvor hat EF den Diskriminatorwert Ihres Entitätstyps in die id
Eigenschaft des Dokuments eingefügt. Wenn Sie beispielsweise einen Entitätstyp Blog
mit einer Id
Eigenschaft mit 8 gespeichert haben, würde die JSON-Eigenschaft id
enthalten Blog|8
.
Neues Verhalten
Ab EF Core 9.0 enthält die JSON-Eigenschaft id
nicht mehr den Diskriminatorwert, sondern nur noch den Wert Ihrer Schlüsseleigenschaft. Im obigen Beispiel wäre die JSON-Eigenschaft id
einfach 8
sein. Falls bei Ihnen in Azure Cosmos DB Dokumente aus früheren Versionen von EF vorhanden sind, weisen diese den Diskriminatorwert in der JSON-Eigenschaft id
auf, und nach dem Upgrade auf EF 9.0 tritt bei Abfragen für diese Dokumente ein Fehler auf.
Warum?
Da die JSON-Eigenschaft id
eindeutig sein muss, wurde früher der Diskriminator hinzugefügt, um die Existenz unterschiedlicher Entitäten mit dem gleichen Schlüsselwert zu ermöglichen. Dadurch konnten beispielsweise innerhalb des gleichen Containers und der gleichen Partition ein Blog
und ein Post
mit einer Id
-Eigenschaft vorhanden sein, die den Wert 8 enthält. Dies passte besser zu Datenmodellierungsmustern relationaler Datenbanken, bei denen jeder Entitätstyp einer eigenen Tabelle zugeordnet ist und somit über einen eigenen Schlüsselraum verfügt.
EF 9.0 hat allgemein die Zuordnung verändert, um sie besser an gängige Azure Cosmos DB-NoSQL-Praktiken und -Erwartungen anzupassen, anstatt den Erwartungen von Benutzern zu entsprechen, die von relationalen Datenbanken kommen. Darüber hinaus erschwerte das Verwenden des Diskriminatorwerts in der id
Eigenschaft die Interaktion mit externen Tools und Systemen mit EF-generierten JSON-Dokumenten. Solche externen Systeme sind den EF-Diskriminatorwerten, die standardmäßig von .NET-Typen abgeleitet sind, nicht bekannt.
Gegenmaßnahmen
Die einfachste Entschärfung besteht darin, EF so zu konfigurieren, dass er den Diskriminator wie zuvor in die JSON-Eigenschaft id
einschließt. Zu diesem Zweck wurde eine neue Konfigurationsoption eingeführt:
modelBuilder.Entity<Session>().HasDiscriminatorInJsonId();
Dadurch verhält sich EF für alle Entitätstypen auf oberster Ebene genau wie zuvor.
Wenn Sie möchten, können Sie auch alle Ihre Dokumente aktualisieren, um ihre JSON-Eigenschaft id
neu zu schreiben. Beachten Sie, dass dies nur möglich ist, wenn Entitäten unterschiedlicher Typen nicht den gleichen ID-Wert innerhalb desselben Containers gemeinsam verwenden.
Die JSON-id
-Eigenschaft wird dem Schlüssel zugeordnet.
Altes Verhalten
Zuvor hat EF eine Schatteneigenschaft erstellt, die der JSON-id
-Eigenschaft zugeordnet ist, es sei denn, einer der Eigenschaften wurde explizit id
zugeordnet.
Neues Verhalten
Ab EF Core 9 wird die Schlüsseleigenschaft nach Möglichkeit der JSON-id
-Eigenschaft zugeordnet. Dies bedeutet, dass die Schlüsseleigenschaft nicht mehr unter einem anderen Namen mit demselben Wert beibehalten wird, sodass Nicht-EF-Code, der die Dokumente verwendet und diese Eigenschaft nutzt, nicht mehr korrekt funktioniert.
Warum?
EF 9.0 hat die Zuordnung im Allgemeinen so geändert, dass sie besser auf die gängigen Azure Cosmos DB NoSQL-Praktiken und -Erwartungen abgestimmt wird. Und es ist nicht üblich, den Schlüsselwert zweimal im Dokument zu speichern.
Gegenmaßnahmen
Wenn Sie das EF Core 8-Verhalten beibehalten möchten, besteht die einfachste Entschärfung darin, eine neue Konfigurationsoption zu verwenden, die zu diesem Zweck eingeführt wurde:
modelBuilder.Entity<Session>().HasShadowId();
Dadurch verhält sich EF für alle Entitätstypen auf oberster Ebene genau wie zuvor. Sie können sie auch auf alle Entitätstypen im Modell mit einem Aufruf anwenden:
modelBuilder.HasShadowIds();
Änderungen mit mittlerer Auswirkung
Die Synchronisierung von E/A über den Azure Cosmos DB-Anbieter wird nicht mehr unterstützt
Nachverfolgung von Issue 32563
Altes Verhalten
Das Aufrufen synchroner Methoden wie ToList
oder SaveChanges
würde dazu führen, dass EF Core beim Ausführen asynchroner Aufrufe für das Azure Cosmos DB SDK synchron mit .GetAwaiter().GetResult()
blockiert wird. Dies kann zu Deadlock führen.
Neues Verhalten
Ab EF Core 9.0 wird EF jetzt standardmäßig ausgelöst, wenn versucht wird, synchronen E/A zu verwenden. Die Ausnahmemeldung lautet „Azure Cosmos DB unterstützt keinen synchronen E/A.“ Stellen Sie sicher, dass Sie nur asynchrone Methoden verwenden und richtig auf sie warten, wenn Sie Entity Framework Core für den Zugriff auf Azure Cosmos DB verwenden. Weitere Informationen finden Sie unter https://aka.ms/ef-cosmos-nosync.
Warum?
Synchrone Blockierung von asynchronen Methoden kann zu Deadlock führen, und das Azure Cosmos DB SDK unterstützt nur asynchrone Methoden.
Gegenmaßnahmen
In EF Core 9.0 kann der Fehler unterdrückt werden mit:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.ConfigureWarnings(w => w.Ignore(CosmosEventId.SyncNotSupported));
}
Das heißt, Anwendungen sollten die Verwendung von Synchronisierungs-APIs mit Azure Cosmos DB beenden, da dies nicht vom Azure Cosmos DB SDK unterstützt wird. Die Möglichkeit, die Ausnahme zu unterdrücken, wird in einer zukünftigen Version von EF Core entfernt, wonach die einzige Option die Verwendung asynchroner APIs sein wird.
SQL-Abfragen müssen jetzt JSON-Werte direkt projizieren
Altes Verhalten
Zuvor generierte EF Abfragen wie die folgenden:
SELECT c["City"] FROM root c
Solche Abfragen führen dazu, dass Azure Cosmos DB jedes Ergebnis wie folgt in ein JSON-Objekt einschließt:
[
{
"City": "Berlin"
},
{
"City": "México D.F."
}
]
Neues Verhalten
Ab EF Core 9.0 fügt EF nun den VALUE
Modifizierer zu Abfragen wie folgt hinzu:
SELECT VALUE c["City"] FROM root c
Solche Abfragen führen dazu, dass Azure Cosmos DB die Werte direkt zurückgibt, ohne sie einzuschließen:
[
"Berlin",
"México D.F."
]
Wenn Ihre Anwendung SQL-Abfragen verwendet, werden solche Abfragen wahrscheinlich nach dem Upgrade auf EF 9.0 unterbrochen, da sie den VALUE
Modifizierer nicht enthalten.
Warum?
Jedes Ergebnis in ein zusätzliches JSON-Objekt zu verpacken, kann in einigen Szenarien zu Leistungseinbußen führen, vergrößert die JSON-Ergebnis-Nutzlast und ist nicht die optimale Art, mit Azure Cosmos DB zu arbeiten.
Gegenmaßnahmen
Um dies zu vermeiden, fügen Sie einfach den VALUE
Modifizierer zu den Projektionen Ihrer SQL-Abfragen hinzu, wie oben gezeigt.
Nicht definierte Ergebnisse werden jetzt automatisch aus Abfrageergebnissen gefiltert
Altes Verhalten
Zuvor generierte EF Abfragen wie die folgenden:
SELECT c["City"] FROM root c
Solche Abfragen führen dazu, dass Azure Cosmos DB jedes Ergebnis wie folgt in ein JSON-Objekt einschließt:
[
{
"City": "Berlin"
},
{
"City": "México D.F."
}
]
Wenn eines der Ergebnisse nicht definiert war (z. B. die City
Eigenschaft fehlte im Dokument), wurde ein leeres Dokument zurückgegeben, und EF würde null
für dieses Ergebnis zurückgeben.
Neues Verhalten
Ab EF Core 9.0 fügt EF nun den VALUE
Modifizierer zu Abfragen wie folgt hinzu:
SELECT VALUE c["City"] FROM root c
Solche Abfragen führen dazu, dass Azure Cosmos DB die Werte direkt zurückgibt, ohne sie einzuschließen:
[
"Berlin",
"México D.F."
]
Das Azure Cosmos DB-Verhalten besteht darin, undefined
-Werte automatisch aus Ergebnissen zu filtern. Wenn also eine der City
-Eigenschaften nicht im Dokument vorhanden ist, gibt die Abfrage nur ein einzelnes Ergebnis zurück, und das andere ist null
.
Warum?
Jedes Ergebnis in ein zusätzliches JSON-Objekt zu verpacken, kann in einigen Szenarien zu Leistungseinbußen führen, vergrößert die JSON-Ergebnis-Nutzlast und ist nicht die optimale Art, mit Azure Cosmos DB zu arbeiten.
Gegenmaßnahmen
Wenn das Abrufen von null
Werten für nicht definierte Ergebnisse für Ihre Anwendung wichtig ist, werden die undefined
Werte zu null
zusammengefasst, um den neuen EF.Functions.Coalesce
Operator zu verwenden:
var users = await context.Customer
.Select(c => EF.Functions.CoalesceUndefined(c.City, null))
.ToListAsync();
Falsch übersetzte Abfragen werden nicht mehr übersetzt
Altes Verhalten
Zuvor übersetzte EF Abfragen wie die folgende:
var sessions = await context.Sessions
.Take(5)
.Where(s => s.Name.StartsWith("f"))
.ToListAsync();
Die SQL-Übersetzung für diese Abfrage war jedoch falsch:
SELECT c
FROM root c
WHERE ((c["Discriminator"] = "Session") AND STARTSWITH(c["Name"], "f"))
OFFSET 0 LIMIT @__p_0
In SQL wird die WHERE
Klausel vor den OFFSET
und LIMIT
Klauseln ausgewertet. In der obigen LINQ-Abfrage wird der Take
Operator jedoch vor dem Where
Operator angezeigt. Daher könnten solche Abfragen falsche Ergebnisse zurückgeben.
Neues Verhalten
Ab EF Core 9.0 werden solche Abfragen nicht mehr übersetzt, und eine Ausnahme wird ausgelöst.
Warum?
Falsche Übersetzungen können zu einer automatischen Datenbeschädigung führen, was zu schwer zu erkennenden Fehlern in Ihrer Anwendung führen kann. EF bevorzugen es immer, schnell zu ausfallen, indem sie vorab ausgelöst werden, anstatt möglicherweise zu Datenbeschädigungen zu führen.
Gegenmaßnahmen
Wenn Sie mit dem vorherigen Verhalten zufrieden waren und dasselbe SQL ausführen möchten, tauschen Sie einfach die Reihenfolge der LINQ-Operatoren aus:
var sessions = await context.Sessions
.Where(s => s.Name.StartsWith("f"))
.Take(5)
.ToListAsync();
Leider unterstützt Azure Cosmos DB die Klauseln OFFSET
und LIMIT
in SQL-Unterabfragen derzeit nicht, was für die ordnungsgemäße Übersetzung der ursprünglichen LINQ-Abfrage erforderlich ist.
Änderungen mit geringer Auswirkung
HasIndex
wird jetzt ausgelöst, anstatt ignoriert zu werden
Altes Verhalten
Zuvor wurden Aufrufe HasIndex vom EF Cosmos DB-Anbieter ignoriert.
Neues Verhalten
Der Anbieter löst jetzt aus, wenn HasIndex angegeben wird.
Warum?
In Azure Cosmos DB werden alle Eigenschaften standardmäßig indiziert, und es muss keine Indizierung angegeben werden. Obwohl es möglich ist, eine benutzerdefinierte Indizierungsrichtlinie zu definieren, wird dies derzeit nicht von EF unterstützt und kann über das Azure-Portal ohne EF-Unterstützung erfolgen. Da HasIndex Aufrufe nichts getan haben, sind sie nicht mehr zulässig.
Gegenmaßnahmen
Entfernen Sie alle Aufrufe von HasIndex.
IncludeRootDiscriminatorInJsonId
wurde nach 9.0.0-rc.2 in HasRootDiscriminatorInJsonId
umbenannt
Altes Verhalten
Die API IncludeRootDiscriminatorInJsonId
wurde in 9.0.0 rc.1 eingeführt.
Neues Verhalten
Für die endgültige Version von EF Core 9.0 wurde die API umbenannt in HasRootDiscriminatorInJsonId
Warum?
Eine andere verwandte API wurde umbenannt, um mit Has
statt Include
zu beginnen, und daher wurde diese API auch für Konsistenz umbenannt.
Gegenmaßnahmen
Wenn Ihr Code die IncludeRootDiscriminatorInJsonId
API verwendet, ändern Sie ihn einfach so, dass er stattdessen HasRootDiscriminatorInJsonId
referenziert.