Freigeben über


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.

Wichtige Änderung Auswirkung
EF.Functions.Unhex() gibt jetzt byte[]? zurück Niedrig
Die NULL-Zulässigkeitsargumente von SqlFunctionExpression Niedrig
ToString()-Methode gibt jetzt für null-Instanzen eine leere Zeichenfolge zurück Niedrig
Abhängigkeiten des freigegebenen Frameworks wurden auf 9.0.x aktualisiert Niedrig

Ä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.

Wichtige Änderung Auswirkung
Die Diskriminatoreigenschaft wird jetzt $type anstelle von Discriminator genannt Hoch
Die id Eigenschaft enthält standardmäßig nicht mehr den Diskriminator Hoch
Die Synchronisierung von E/A über den Azure Cosmos DB-Anbieter wird nicht mehr unterstützt Medium
SQL-Abfragen müssen jetzt JSON-Werte direkt projizieren Medium
Nicht definierte Ergebnisse werden jetzt automatisch aus Abfrageergebnissen gefiltert Medium
Falsch übersetzte Abfragen werden nicht mehr übersetzt Medium
HasIndex wird jetzt ausgelöst, anstatt ignoriert zu werden Niedrig
IncludeRootDiscriminatorInJsonId wurde nach 9.0.0-rc.2 in HasRootDiscriminatorInJsonId umbenannt Niedrig

Änderungen mit hoher Auswirkung

Die Diskriminatoreigenschaft wird jetzt $type anstelle von Discriminator genannt

Issue #34269

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.

Issue #34179

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.

Ä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

Issue #25527

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

Issue #25527

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 nullzusammengefasst, 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

Issue #34123

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

Issue #34023

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

Issue #34717

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.