Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Diese Seite dokumentiert API- und Verhaltensänderungen, die das Potenzial haben, vorhandene Anwendungen, die von EF Core 10 auf EF Core 11 aktualisiert werden, zu unterbrechen. Überprüfen Sie frühere grundlegende Änderungen, wenn sie von einer früheren Version von EF Core aktualisiert werden:
- Grundlegende Änderungen in EF Core 10
- Grundlegende Änderungen in EF Core 9
- Grundlegende Änderungen in EF Core 8
Zusammenfassung
Hinweis
Wenn Sie Microsoft.Data.Sqlite verwenden, lesen Sie den separaten Abschnitt weiter unten zu den Breaking Changes in Microsoft.Data.Sqlite.
Änderungen mit hoher Auswirkung
Cosmos: Nicht zugeordnete Eigenschaften bleiben nicht mehr erhalten
Altes Verhalten
Wenn EF Core ein Cosmos DB-Dokument liest, das JSON-Eigenschaften enthielt, die nicht im EF-Modell zugeordnet wurden, wurden diese zusätzlichen Eigenschaften in der __jObject Schatteneigenschaft beibehalten und in die Datenbank zurückgeschrieben SaveChanges. Nicht zugeordnete Daten in Dokumenten wurden transparent gerundet.
Neues Verhalten
Ab EF Core 11 werden nicht zugeordnete JSON-Eigenschaften in einem Cosmos DB-Dokument beim Lesen ignoriert. Alle zusätzlichen Eigenschaften, die nicht Teil des EF-Modells sind, gehen verloren, wenn die Entität anschließend gespeichert wird.
Warum
Da __jObject entfernt wurde (siehe Cosmos: __jObject Schatteneigenschaft entfernt; JObject wird nicht mehr für die Serialisierung verwendet), es gibt keinen Mechanismus, um nicht zugeordnete Eigenschaften beizubehalten. EF Core 11 verwendet einen schlanken JSON-Reader, der nur die Eigenschaften verarbeitet, die es aus dem Modell kennt.
Gegenmaßnahmen
Wenn Ihre Anwendung auf die Beibehaltung nicht zugeordneter Daten angewiesen ist, sollten Sie eine der folgenden Optionen in Betracht ziehen:
-
Verwenden Sie
CosmosClientdirekt für Dokumente, bei denen Sie vollzugriff auf das JSON-Shape benötigen. - Ordnen Sie alle relevanten Eigenschaften explizit in Ihrem EF-Modell zu, einschließlich aller zusätzlichen Felder, die beibehalten werden sollen.
Änderungen mit mittlerer Auswirkung
Die Sync-I/O-Funktionalität über den Azure Cosmos DB-Anbieter wurde vollständig entfernt.
Nachverfolgung von Issue 37059
Altes Verhalten
Synchrone E/A über den Azure Cosmos DB-Anbieter wird seit EF 9.0 (note) nicht unterstützt. Das Aufrufen einer Synchronisierungs-E/A-API wie ToList oder SaveChanges hat eine Ausnahme ausgelöst, es sei denn, eine spezielle Opt-In wurde konfiguriert. Wenn die Opt-In konfiguriert wurde, funktionierten Synchronisierungs-E/A-APIs wie zuvor, wodurch der Anbieter eine "sync-over-async"-Blockierung für das Azure Cosmos DB SDK durchführt, was zu Deadlocks und anderen Leistungsproblemen führen kann.
Neues Verhalten
Ab EF Core 11.0 löst EF nun immer eine Ausnahme aus, wenn eine API mit synchronen E/A-Vorgängen aufgerufen wird. Es gibt keine Möglichkeit, die Verwendung von synchronen E/A-APIs wieder zu aktivieren.
Warum
Das synchrone Blockieren asynchroner Methoden ("sync-over-async") wird dringend abgeraten und kann zu Deadlock- und anderen Leistungsproblemen führen. Da das Azure Cosmos DB SDK nur asynchrone Methoden unterstützt, unterstützt auch der EF Cosmos-Anbieter asynchrone Methoden.
Gegenmaßnahmen
Konvertieren Sie Ihren Code, um asynchrone E/A-APIs anstelle von Synchronisierungs-E/A-APIs zu verwenden. Ersetzen Sie z. B. Aufrufe von SaveChanges() durch await SaveChangesAsync().
Microsoft. Data.SqlClient wurde auf 7.0 aktualisiert.
Altes Verhalten
EF Core 10 verwendete Microsoft.Data.SqlClient 6.x, das Azure/Entra ID-Authentifizierungsabhängigkeiten (z. B. Azure.Core, Azure.Identity und Microsoft.Identity.Client) im Kernpaket enthielt.
Neues Verhalten
EF Core 11 hängt jetzt von Microsoft ab. Data.SqlClient 7.0. Diese Version entfernt Azure/Entra ID (ehemals Azure Active Directory) Authentifizierungsabhängigkeiten aus dem Kernpaket. Wenn Ihre Anwendung Entra ID Authentifizierung verwendet (z. B. ActiveDirectoryDefault, ActiveDirectoryInteractive, ActiveDirectoryManagedIdentity oder ActiveDirectoryServicePrincipal), müssen Sie das paket Microsoft.Data.SqlClient.Extensions.Azure jetzt separat installieren.
Darüber hinaus wurde SqlAuthenticationMethod.ActiveDirectoryPassword als veraltet markiert.
Weitere Informationen finden Sie im Microsoft. Data.SqlClient 7.0 Versionshinweise.
Warum
Diese Änderung wurde in Microsoft vorgenommen. Data.SqlClient um Abhängigkeitsblähigkeiten für Anwendungen zu reduzieren, die keine Azure Authentifizierung verwenden, was insbesondere für containerisierte Bereitstellungen und lokale Entwicklung von Vorteil ist.
Gegenmaßnahmen
Wenn Ihre Anwendung Entra ID Authentifizierung mit SQL Server verwendet, fügen Sie einen Verweis auf das paket Microsoft.Data.SqlClient.Extensions.Azure in Ihrem Projekt hinzu:
<PackageReference Include="Microsoft.Data.SqlClient.Extensions.Azure" Version="7.0.0" />
Es sind keine Codeänderungen erforderlich, die über das Hinzufügen dieses Paketverweises hinausgehen. Wenn Sie SqlAuthenticationMethod.ActiveDirectoryPassword verwenden, migrieren Sie zu einer modernen Authentifizierungsmethode, wie ActiveDirectoryDefault oder ActiveDirectoryInteractive.
Cosmos: illegale id-Zeichen werden nicht mehr maskiert
Altes Verhalten
Beim Generieren des Cosmos-id-Eigenschaftswerts aus einem zusammengesetzten Schlüssel, der mehrere Teile enthält, hat der Azure Cosmos DB-Anbieter bestimmte Zeichen, die in id-Werten von Cosmos-Ressourcen unzulässig sind, mit Escapezeichen versehen:
| Character | Maskiert als |
|---|---|
/ |
^2F |
\ |
^5C |
? |
^3F |
# |
^23 |
Neues Verhalten
Seit EF Core 11.0 werden diese Zeichen im generierten id-Wert nicht mehr mit Escapezeichen maskiert. Der id Wert enthält die Rohschlüsselwerte ohne Änderung. Beachten Sie, dass, wenn id-Werte verkettet werden (d. h. wenn ein zusammengesetzter Schlüssel verwendet wird oder das Verhalten discriminator-in-id aktiviert ist), das Zeichen | als Trennzeichen verwendet wird — und bereits in Schlüsselwerten vorhandene |-Zeichen maskiert werden, um Mehrdeutigkeiten zu vermeiden. Es wird keine andere Maskierung angewendet.
Das alte Escapeverhalten kann durch Festlegen eines AppContext Schalters erneut aktiviert werden:
AppContext.SetSwitch("Microsoft.EntityFrameworkCore.EscapeIllegalCosmosIdCharacters", true);
Warum
Das vorherige Maskierungsschema war nicht injektiv: das Escapezeichen ^ wurde nie selbst maskiert. Dies bedeutete, dass ein Schlüsselwert, der die Literalzeichenfolge ^2F enthielt, dasselbe id erzeugte wie ein Schlüsselwert, der / enthielt, was zu stiller Datenkorruption führte, bei der zwei Entitäten mit unterschiedlichen Primärschlüsseln demselben Cosmos-Dokument zugeordnet würden. Durch das Beenden der Flucht wird das Kollisionsproblem vollständig behoben.
Gegenmaßnahmen
Wenn Ihre Anwendung zusammengesetzte Schlüssel verwendet, deren Werte die Zeichen /, \, ? oder # enthalten können, sollten Sie Folgendes beachten:
-
Vorhandene Daten: Dokumente, die zuvor in Cosmos DB gespeichert wurden, weisen
idWerte mit den alten Escapesequenzen auf (z. B.Post|1|^2F). Nach dem Upgrade auf EF Core 11 generiert EF nicht maskierteid-Werte (z. B.Post|1|/) und findet diese bereits vorhandenen Dokumente nicht mehr. Um weiterhin ohne Migration auf vorhandene Daten zugreifen zu können, aktivieren Sie mit dem oben beschriebenenAppContext-Schalter erneut das alte Verhalten. Beachten Sie jedoch, dass der ID-Kollisionsfehler weiterhin vorhanden ist. -
Neue Daten: Wenn Sie eine neue Anwendung oder Datenbank erstellen, vermeiden Sie die Verwendung dieser unzulässigen Zeichen in Schlüsselwerten, da sie in Cosmos DB-Ressourcenwerten
idnicht gültig sind. Weitere Informationen finden Sie in der dokumentation Azure.
Cosmos: Ausnahme ausgelöst, wenn eine Projektion als nicht definiert ausgewertet wird
Altes Verhalten
Beim Projizieren von Eigenschaften in anonymen Typ- oder DTO-Projektionen über die Navigation über optionale Beziehungen, bei denen ein Segment des Pfads im Cosmos DB-Dokument nicht vorhanden war (was dazu führt, dass der projizierte Wert zu sein undefinedhat), war das Verhalten inkonsistent:
- Mit anonymen Single-Property-Typen oder DTO-Projektionen übersetzte EF die Abfrage mithilfe
SELECT VALUEvon , die im Hintergrund alle Dokumente herausfilterte, in denen der projizierte Wert warundefined. Dies bedeutete, dass weniger Ergebnisse zurückgegeben wurden als erwartet, ohne angabe der fehlenden Daten. - Bei anonymen Multi-Property-Typen oder DTO-Projektionen wurde eine
InvalidOperationExceptionMeldung mit der Meldung "Nullable-Objekt muss einen Wert aufweisen" ausgelöst.
Beispielsweise, wenn eine Entität Entity mit einem optionalen Besitz verfügt, der wiederum über einen optionalen Besitz AssociateNestedAssociateverfügt:
// Previously silently returned fewer results (undefined results were filtered out)
var singlePropResults = await context.Entities
.Select(x => new { x.Associate!.NestedAssociate!.Id })
.ToListAsync();
// Previously threw InvalidOperationException: Nullable object must have a value
var multiPropResults = await context.Entities
.Select(x => new { x.Associate!.NestedAssociate!.Id, x.Associate!.NestedAssociate!.String })
.ToListAsync();
Neues Verhalten
Ab EF Core 11.0 wird ein InvalidOperationException Fehler in beiden Fällen ausgelöst, wenn ein Teil der Projektion in Azure Cosmos DB ausgewertet wirdundefined. Die Ausnahmemeldung lautet:
Ein Teil der Projektion war nicht definiert und verwendet den Kooperator, um mögliche undefinierte Werte zu behandeln.
Warum
Das vorherige Verhalten war inkonsistent. Single-Property-Projektionen könnten Ergebnisse im Hintergrund verwerfen, sodass Daten ohne Hinweise auf das Problem leicht übersehen werden können. Das neue Verhalten stellt eine konsistente, vorhersagbare Fehlerberichterstattung sicher, wenn eine Projektion auf einen nicht definierten Wert trifft.
Gegenmaßnahmen
Wird IsDefined verwendet, um Dokumente herauszufiltern, in denen der projizierte Wert fehlt:
var results = await context.Entities
.Where(x => EF.Functions.IsDefined(x.Associate!.NestedAssociate!.Id))
.Select(x => new { x.Associate!.NestedAssociate!.Id })
.ToListAsync();
Alternativ können Sie CoalesceUndefined einen Standardwert für Eigenschaften bereitstellen, die folgendes sein undefinedkönnen:
var results = await context.Entities
.Select(x => new
{
Id = EF.Functions.CoalesceUndefined(x.Associate!.NestedAssociate!.Id, Guid.Empty)
})
.ToListAsync();
Änderungen mit geringer Auswirkung
Cosmos: __jObject Schatteneigenschaft entfernt; JObject wird nicht mehr für die Serialisierung verwendet
Altes Verhalten
Zuvor hat der Azure Cosmos DB Anbieter eine Schatteneigenschaft namens "__jObject" Typ JObject (von Newtonsoft.Json) zu jedem Entitätstyp hinzugefügt. Diese Eigenschaft enthielt das unformatierte JSON-Dokument, das von Cosmos DB empfangen und an Cosmos DB gesendet wurde und den Zugriff auf nicht zugeordnete oder rohe Daten ermöglicht:
var order = await context.Orders.FirstAsync();
var rawJson = context.Entry(order).Property<JObject>("__jObject").CurrentValue;
var billingAddress = rawJson["BillingAddress"]?.Value<string>();
EF Core wird intern für alle Dokument serialisierung und Deserialisierung verwendet Newtonsoft.Json (via JObject).
Neues Verhalten
Ab EF Core 11 ist die __jObject Schatteneigenschaft nicht mehr vorhanden. EF Core verwendet System.Text.Json jetzt (Utf8JsonReader/Utf8JsonWriter) für die Dokument serialisierung und Deserialisierung und hängt nicht mehr von Newtonsoft.Json.
Durch den Zugriff auf die "__jObject" Eigenschaft wird ein InvalidOperationException.
Warum
Der JObject-basierte Ansatz erforderte eine Abhängigkeit von Newtonsoft.Json und eingeschränkten Leistungsverbesserungen. Der Wechsel zur System.Text.Json Ausrichtung von EF Core Cosmos an den Rest des .NET Ökosystems und ermöglicht erhebliche Leistungssteigerungen im Materializer.
Gegenmaßnahmen
Verwenden Sie für den Zugriff auf das unformatierte JSON-Dokument die CosmosClient direkte Verwendung, anstatt auf __jObjectfolgendes zu vertrauen:
var cosmosClient = context.Database.GetCosmosClient();
var container = cosmosClient.GetContainer("myDatabase", "myContainer");
var response = await container.ReadItemAsync<JsonElement>("1", new PartitionKey("1"));
var billingAddress = response.Resource.GetProperty("BillingAddress").GetString();
Weitere Informationen finden Sie unter Arbeiten mit unstrukturierten Daten in Azure Cosmos DB.
SQL Server Kompatibilitätsstufe ist jetzt standardmäßig auf 160 festgelegt.
Nachverfolgungsvorgang Nr. 38198
Altes Verhalten
Zuvor wurde EF Core bei Verwendung von UseSqlServer ohne explizite Konfiguration einer SQL Server Kompatibilitätsstufe standardmäßig auf Kompatibilitätsebene 150 festgelegt, die SQL Server 2019 entspricht.
Neues Verhalten
Ab EF Core 11.0 ist UseSqlServer Standardmäßig auf Kompatibilitätsebene 160 festgelegt, die SQL Server 2022 entspricht. Dadurch kann EF SQL generieren, das standardmäßig SQL Server 2022-Features verwendet. Beispielsweise verwenden einige Abfragen jetzt LEAST und GREATEST, einschließlich Übersetzungen für Math.Min, Math.Max, Least, Greatest und einige Take/Skip-Muster.
Wenn Ihre Datenbank auf SQL Server 2019 oder älter ausgeführt wird oder mit einer Kompatibilitätsstufe unter 160 konfiguriert ist, werden einige von EF Core generierte SQL möglicherweise nicht mehr von der Datenbank unterstützt.
Warum
SQL Server 2022 ist seit mehreren Jahren verfügbar, und mit Kompatibilitätsebene 160 kann EF Core standardmäßig einfachere und effizientere SQL für neuere SQL Server Versionen generieren.
Gegenmaßnahmen
Wenn Ihre Datenbank die Kompatibilitätsebene 160 nicht unterstützt, konfigurieren Sie EF Core so, dass die von Der Datenbank unterstützte Kompatibilitätsstufe verwendet wird:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("<connection string>", o => o.UseCompatibilityLevel(150));
}
Weitere Informationen finden Sie in der Dokumentation zur kompatibilitätsstufe SQL Server.
EF Core wird jetzt standardmäßig ausgelöst, wenn keine Migrationen gefunden werden
Altes Verhalten
Zuvor, wenn eine Datenbank ohne Migrationen in der Assembly mit Migrate oder MigrateAsync aufgerufen wurde, protokollierte EF Core eine Informationsnachricht und kehrte zurück, ohne Änderungen anzuwenden.
Neues Verhalten
Ab EF Core 11.0 löst EF Core standardmäßig eine Ausnahme aus, wenn keine Migrationen in der Assembly gefunden werden. Dies entspricht dem verhalten, das PendingModelChangesWarningin EF 9.0 eingeführt wurde.
Warum
Wenn keine Migrationen vorhanden sind und Migrate() oder MigrateAsync() aufgerufen werden, weist dies typischerweise auf eine Fehlkonfiguration hin. Anstatt leise fortzufahren und die Datenbank in einem potenziell falschen Zustand zu belassen, weist EF Core Entwickler jetzt sofort auf dieses Problem hin.
Gegenmaßnahmen
Wenn Sie absichtlich aufrufen Migrate() , ohne Migrationen zu haben (z. B. weil Sie das Datenbankschema auf andere Weise verwalten), entfernen Sie den Migrate() Aufruf, oder unterdrücken Sie die Ausnahme, indem Sie Warnungen konfigurieren:
options.ConfigureWarnings(w => w.Ignore(RelationalEventId.MigrationsNotFound))
Oder um das Ereignis zu protokollieren, anstatt eine Ausnahme auszulösen:
options.ConfigureWarnings(w => w.Log(RelationalEventId.MigrationsNotFound))
Die Eigenschaft EFOptimizeContext wurde entfernt.
Nachverfolgungsproblem Nr. 35079
Altes Verhalten
Zuvor konnte die EFOptimizeContext MSBuild-Eigenschaft auf true festgelegt werden, um während des Build‑ oder Veröffentlichungsvorgangs die Generierung des kompilierten Modells und vorkompilierter Abfragecodes zu aktivieren.
<EFOptimizeContext Condition="'$(Configuration)'=='Release'">true</EFOptimizeContext>
Neues Verhalten
Ab EF Core 11.0 wurde die EFOptimizeContext MSBuild-Eigenschaft entfernt. Die Codegenerierung wird jetzt ausschließlich über die EFScaffoldModelStage- und EFPrecompileQueriesStage-Eigenschaften gesteuert. Wenn PublishAOT auf true festgelegt ist, wird die Codegenerierung während der Veröffentlichung automatisch aktiviert, ohne zusätzliche Eigenschaften zu benötigen.
Warum
Die Eigenschaften EFScaffoldModelStage und EFPrecompileQueriesStage bieten bereits eine differenzierte Kontrolle darüber, wann die Codegenerierung auftritt.
EFOptimizeContext war ein überflüssiges Aktivierungsgate.
Gegenmaßnahmen
Ersetzen Sie die Verwendung von EFOptimizeContext durch die Eigenschaften EFScaffoldModelStage und EFPrecompileQueriesStage. Diese können auf publish oder build festgelegt werden, um zu steuern, in welchem Stadium die Codegenerierung erfolgt:
<EFScaffoldModelStage>publish</EFScaffoldModelStage>
<EFPrecompileQueriesStage>publish</EFPrecompileQueriesStage>
Jeder andere Wert (z. B none. ) deaktiviert die entsprechende Generation.
Wenn Sie PublishAOT auf true gesetzt haben, wird die Codegenerierung beim Veröffentlichen automatisch aktiviert, und es ist keine zusätzliche Konfiguration erforderlich.
EF-Toolspakete verweisen nicht mehr auf Microsoft.EntityFrameworkCore.Design
Altes Verhalten
Zuvor hatten die Microsoft.EntityFrameworkCore.Tools und Microsoft.EntityFrameworkCore.Tasks NuGet-Pakete eine Abhängigkeit von Microsoft.EntityFrameworkCore.Design.
Neues Verhalten
Ab EF Core 11.0 haben die Microsoft.EntityFrameworkCore.Tools und Microsoft.EntityFrameworkCore.Tasks NuGet-Pakete keine Abhängigkeit mehr von Microsoft.EntityFrameworkCore.Design.
Warum
Es gab keine feste Abhängigkeit vom Code in Microsoft.EntityFrameworkCore.Design, und diese Abhängigkeit führte zu Problemen, wenn die neueste Version von Microsoft.EntityFrameworkCore.Tools in Projekten verwendet wurde, die auf ältere Frameworks abzielten.
Gegenmaßnahmen
Wenn Ihr Projekt davon abhängt, dass Microsoft.EntityFrameworkCore.Design transitiv über die Toolspakete bereitgestellt wird, fügen Sie in Ihrem Projekt einen direkten Verweis darauf hinzu.
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="11.0.0" PrivateAssets="all" />
SqlVector-Eigenschaften werden standardmäßig nicht mehr geladen.
Altes Verhalten
Bisher hat EF Core beim Abfragen von Entitäten mit SqlVector<T>-Eigenschaften die Vektorspalte in SELECT-Anweisungen aufgenommen und die Eigenschaft in der zurückgegebenen Entität befüllt.
Neues Verhalten
Beim Materialisieren von Entitäten ab EF Core 11.0 sind SqlVector<T>-Eigenschaften nicht mehr in SELECT-Anweisungen enthalten. Die Eigenschaft ist bei zurückgegebenen Entitäten null.
Vektoreigenschaften können weiterhin in WHERE und ORDER BY Klauseln verwendet werden , einschließlich mit VectorDistance() und VectorSearch(); sie werden nur nicht in die Entitätsprojektion eingeschlossen.
Warum
Vektorspalten können sehr groß sein, die Hunderte oder Tausende von Gleitkommawerten enthalten. In den meisten Fällen werden Vektoren in die Datenbank geschrieben und dann für die Suche verwendet, ohne dass sie gelesen werden müssen. Indem Sie sie standardmäßig von SELECT ausschließen, werden unnötige Datenübertragungen vermieden.
Gegenmaßnahmen
Hinweis
Ein Mechanismus, um Vektoreigenschaften wieder für das automatische Laden zu aktivieren, wird später im Verlauf der Veröffentlichung von EF Core 11 eingeführt.
Wenn Sie Vektor-Werte zurücklesen möchten, verwenden Sie eine explizite Projektion.
var embeddings = await context.Blogs
.Select(b => new { b.Id, b.Embedding })
.ToListAsync();
Cosmos: Leere Sammlungen geben jetzt eine leere Sammlung anstelle von NULL zurück.
Nachverfolgung von Issue 36577
Altes Verhalten
Bisher war die Collection‑Eigenschaft auf der materialisierten Entität null, wenn beim Abfragen über den Azure Cosmos DB-Anbieter eine eigenständige Sammlung keine Elemente enthielt.
Neues Verhalten
Ab EF Core 11.0 initialisiert der Azure Cosmos DB-Anbieter ordnungsgemäß leere eigenständige Sammlungen, wobei anstelle von null eine leere Sammlung zurückgegeben wird.
Warum
Das vorherige Verhalten, leere eigene Sammlungen als null zu materialisieren, war ein Fehler.
Gegenmaßnahmen
Wenn Ihr Code die Eigenschaften der eigenen Sammlung null explizit überprüft, um zu erkennen, dass die Auflistung leer ist, können diese Prüfungen einfach entfernt werden, da die Auflistung jetzt immer initialisiert wird:
// Before
if (entity.OwnedCollection is null or { Count: 0 })
{
// treated as empty
}
// After
if (entity.OwnedCollection is { Count: 0 })
{
// treated as empty
}
Cosmos: Die Standardmäßige Diskriminatoreigenschaft wird nun im Modell benannt Discriminator .
Altes Verhalten
EF fügt automatisch eine Diskriminatoreigenschaft hinzu, um den Entitätstyp zu identifizieren, den ein JSON-Dokument darstellt. Der Name dieser Eigenschaft im JSON-Dokument wurde von Discriminator$typeEF Core 9.0 in "EF Core 9.0" geändert. Um dies zu erreichen, wird EF sowohl im EF-Modell als auch im gespeicherten JSON-Dokument als Name der Diskriminatoreigenschaft verwendet $type .
Da $type es sich nicht um einen gültigen C#-Bezeichner handelt, verursachte der resultierende Schatteneigenschaftsname ungültigen Code für kompilierte Modelle und vorkompilierte Abfragen , die mit Native AOT verwendet werden.
Neues Verhalten
Ab EF Core 11.0 wird die Standarddiskriminatoreigenschaft erneut im EF-Modell benannt Discriminator , während der in das JSON-Dokument geschriebene Name unverändert bleibt und standardmäßig bleibt $type . Mit anderen Worten: Der Name der Modelleigenschaft und der JSON-Eigenschaftsname werden jetzt entkoppelt:
-
entityType.FindDiscriminatorProperty().NamegibtDiscriminatorzurück. -
entityType.FindDiscriminatorProperty().GetJsonPropertyName()gibt$typezurück.
Das Format der gespeicherten Dokumente ist von dieser Änderung nicht betroffen, sodass vorhandene Daten ohne Änderung weiterhin funktionieren.
Warum
EF leitet einige generierte C#-Bezeichner (z. B. Schatteneigenschaftenvariablennamen) von Modellmetadaten wie Eigenschaftennamen ab. Da $type es sich nicht um einen gültigen C#-Bezeichner handelt, wurde der Modelleigenschaftsname als nicht kompilierbarer Code für kompilierte Modelle und vorkompilierte Abfragen erstellt. Das Benennen der Modelleigenschaft Discriminator (ein gültiger Bezeichner) beim Schreiben $type in das Dokument hält generierten Code gültig, ohne das Format auf dem Datenträger zu ändern.
Gegenmaßnahmen
Für die meisten Anwendungen ist keine Aktion erforderlich, da gespeicherte Dokumente nicht betroffen sind und weiterhin verwendet werden $type.
Wenn Ihr Code auf den Diskriminator anhand des Modelleigenschaftsnamens $type verweist (z. B. über Property einen Abfrage- oder Abfragefilter oder durch Suchen der Eigenschaft in den Metadaten), aktualisieren Sie ihn stattdessen so, dass er verwendet wirdDiscriminator:
// Before
var query = context.Set<Session>().Where(e => EF.Property<string>(e, "$type") == "Lecture");
// After
var query = context.Set<Session>().Where(e => EF.Property<string>(e, "Discriminator") == "Lecture");
Verwenden Sie zum Ändern des JSON-Diskriminator-Eigenschaftsnamens für das gesamte Modell an einer zentralen Stelle, um ihn beispielsweise an der Modelleigenschaftsname auszurichten. Verwenden Sie die API auf Modellebene HasEmbeddedDiscriminatorName , anstatt jeden Entitätstyp einzeln zu konfigurieren:
modelBuilder.HasEmbeddedDiscriminatorName("Discriminator");
Wenn Sie nur den JSON-Namen für einen bestimmten Entitätstyp ändern möchten, um ihn beispielsweise an den Modelleigenschaftsnamen auszurichten, konfigurieren Sie den JSON-Namen der Diskriminatoreigenschaft mit ToJsonProperty:
modelBuilder.Entity<Session>().Property<string>("Discriminator").ToJsonProperty("Discriminator");
Um das vorherige Verhalten wiederherzustellen, bei dem die Diskriminatoreigenschaft auch im Modell benannt $type ist, konfigurieren Sie den Namen explizit mit HasDiscriminator. Beachten Sie, dass dadurch ein ungültiger C#-Bezeichner erneut eingeführt wird und nicht empfohlen wird, wenn kompilierte Modelle oder vorkompilierte Abfragen verwendet werden:
modelBuilder.Entity<Session>().HasDiscriminator<string>("$type");
Cosmos: Gleitkommawerte werden jetzt abgeschnitten, wenn sie in Festkommatypen materialisiert werden
Altes Verhalten
Früher, als eine Abfrageprojektion einen Gleitkommawert (z. B. das Ergebnis eines numerischen Ausdrucks, z 3 / 4 . B. von Cosmos als 0.75zurückgegeben), und die Zieleigenschaft war ein Festkommatyp (int, long, decimalusw.), würde EF Core den Wert runden . Beispiel: 0.75 Würde 1als .
Neues Verhalten
Ab EF Core 11 werden solche Werte abgeschnitten und nicht gerundet .
0.75wird nun als 0übereinstimmender Standard .NET Ganzzahlabkürzungsverhalten ((int)0.75 == 0) materialisiert.
Warum
Die Abkürzung ist das Standardverhalten .NET Verhalten für explizite numerische Konvertierungen und entspricht dem Verhalten anderer Anbieter. Das vorherige Rundungsverhalten war ein Fehler.
Gegenmaßnahmen
Wenn Sie sich auf das vorherige Rundungsverhalten verlassen haben, wenden Sie die explizite Rundung in Ihren Abfragen an, indem Sie Folgendes verwenden Math.Round:
var result = await context.Products
.Select(p => (int)Math.Round((double)p.Int / (p.Int + 1)))
.SingleAsync();
Besitzer-JSON-Auflistungen ohne expliziten Schlüssel sind veraltet
Altes Verhalten
Zuvor konnten besitzereigene Entitätstypen, die einer JSON-Spalte ToJson zugeordnet sind, als Sammlungen verwendet werden, ohne einen expliziten Primärschlüssel zu konfigurieren. EF Core würde im Hintergrund einen ordinalen (positionsbasierten) Schlüssel generieren, um jedes Element in der Sammlung zu identifizieren:
public class Blog
{
public int Id { get; set; }
public List<Post> Posts { get; set; } = new();
}
public class Post
{
// No key property
public required string Title { get; set; }
public required string Content { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.Entity<Blog>().OwnsMany(b => b.Posts, b => b.ToJson());
Neues Verhalten
Ab EF Core 11.0 erzeugt das Konfigurieren einer eigenen JSON-Auflistung ohne expliziten Schlüssel eine OwnedEntityMappedToJsonCollectionWarning Warnung. Die Zuordnung funktioniert weiterhin, gilt jedoch inzwischen als veraltet und wird voraussichtlich in einer künftigen Version entfernt.
Besitzer von JSON-Entitäten, die über einen expliziten Primärschlüssel und nicht sammlungseigene JSON-Verweise verfügen, sind von dieser Änderung nicht betroffen.
Warum
Komplexe Typen wurden in EF Core 10 vollständig unterstützt, einschließlich der JSON-Zuordnung. Komplexe Typen eignen sich für JSON-Dokumente besser als zugeordnete Typen: Sie haben Wertsemantik und besitzen keine eigene Identität, wodurch viele der Probleme vermieden werden, die entstehen, wenn zugeordnete Entitätstypen – die ja Entitätstypen sind – verwendet werden, um etwas zu modellieren, das im Grunde nur ein in ein anderes Dokument eingebetteter Wert ist. Insbesondere waren besessene JSON-Sammlungen ohne expliziten Schlüssel auf einen synthetischen ordinalen Schlüssel angewiesen, der bekannte Einschränkungen und Randfälle aufweist.
Gegenmaßnahmen
Die empfohlene Entschärfung besteht darin, den Typ zu einem komplexen Typ zu migrieren, der jetzt die bevorzugte Methode zum Zuordnen von Typen zu JSON ist:
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.Entity<Blog>().ComplexCollection(b => b.Posts, b => b.ToJson());
Wenn Sie die Zuordnung des eigenen Typs beibehalten müssen, konfigurieren Sie alternativ einen Nicht-Schatten-Primärschlüssel für den eigenen Typ. Nach der Konfiguration eines Schlüssels gilt die Warnung nicht mehr:
public class Post
{
public int Id { get; set; }
public required string Title { get; set; }
public required string Content { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.Entity<Blog>().OwnsMany(b => b.Posts, b =>
{
b.ToJson();
b.HasKey(p => p.Id);
});
Wenn Sie die Migration nicht sofort ausführen können, können Sie die Warnung über ConfigureWarningsFolgendes unterdrücken:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.ConfigureWarnings(w => w.Ignore(CoreEventId.OwnedEntityMappedToJsonCollectionWarning));
Property Keine primitiven Auflistungen mehr konfigurieren
Altes Verhalten
Zuvor könnte das Aufrufen Property eines Elements, dessen CLR-Typ eine Auflistung ist (z. B List<int>. ) dazu führen, dass das Element als grundtypsammlung konfiguriert wird, da eine Eigenschaft basierend auf dem Typ zu einer primitiven Auflistung bei der Modellabschlussung heraufgestuft werden kann.
Neues Verhalten
Ab EF Core 11.0 wird festgelegt, ob es sich bei einer Eigenschaft um eine primitive Auflistung handelt, vollständig bestimmt wird, wenn die Eigenschaft konfiguriert ist. Eine grundtypsammlung muss mit PrimitiveCollection einer (oder als eine nach Konvention ermittelt) konfiguriert werden. Property konfiguriert das Element jetzt immer als nicht-Sammlungseigenschaft (Skalar) und es gibt keine Finalisierungszeitheraufwertung mehr zu einer primitiven Auflistung.
Warum
Die Behandlung des Elementtyps als Endisierungszeitbedenken führte zu Inkonsistenzen und Fehlern. Beispielsweise könnte eine Eigenschaft als primitive Auflistung ermittelt werden, aber später über einen geerbten Wertkonverter zu einem Skalar aufgelöst werden, wobei ein veralteter Elementtyp verlassen wird, der zu einem Abschluss des InvalidCastException Modells führte. Die Erstellung von Primitivensammlungen zu einem Erstellungszeitproblem macht auch die Zuordnung eindeutig in Fällen wie byte[], in denen andernfalls unklar ist, ob das Element als binäre Skalar oder als Sammlung von Bytes zugeordnet werden soll.
Gegenmaßnahmen
Wenn Sie sich auf die Property Konfiguration einer primitiven Auflistung verlassen haben, wechseln Sie stattdessen zu PrimitiveCollection :
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.Entity<Blog>().PrimitiveCollection(b => b.Tags);
In den meisten Fällen ist keine Änderung erforderlich, da primitive Auflistungen konventionslos ermittelt werden.
Geteilte Abfragen werden jetzt ausgelöst, wenn gleichzeitige Änderungen erkannt werden
Altes Verhalten
Wenn eine geteilte Abfrage (mithilfe AsSplitQuery()von ) nicht sortierten oder verwaisten untergeordneten Zeilen aufgetreten ist, die durch gleichzeitige Datenänderungen zwischen den SQL-Anweisungen der geteilten Abfrage verursacht wurden, verworfen EF Core die betroffenen untergeordneten Auflistungen im Hintergrund. Das Ergebnis war eine Entität mit einer leeren Auflistung, obwohl die zugehörigen Zeilen noch vorhanden waren – es wurde keine Ausnahme ausgelöst, und es wurde keine Warnung protokolliert.
Neues Verhalten
Ab EF Core 11.0 löst EF Core ein DbQueryConcurrencyException , wenn geteilte Abfrageergebnisse aufgrund gleichzeitiger Datenänderungen nicht korreliert werden können. Die Ausnahmemeldung beschreibt die Situation und schlägt Abhilfe vor:
Die Ergebnisse einer geteilten Abfrage konnten nicht korreliert werden, da die Daten während der Ausführung der Abfrage gleichzeitig geändert wurden. Führen Sie die Abfrage erneut aus, oder führen Sie sie in einer serialisierbaren oder Momentaufnahmetransaktion aus, um gleichzeitige Änderungen zu verhindern.
Warum
Das automatische Zurückgeben falscher Daten (leere Auflistungen für Entitäten mit verknüpften Zeilen) ist viel schlimmer als das Auftreten eines Fehlers. Dieses Szenario wird durch das Fehlen von Datenkonsistenzgarantien in geteilten Abfragen verursacht, wenn die Datenbank zwischen Anweisungen geändert wird. Das Auslösen einer erneuten Ausnahme macht das Problem sichtbar und gibt Anrufern einen klaren Pfad zur Wiederherstellung.
Gegenmaßnahmen
Die einfachste Entschärfung besteht darin, die Abfrage erneut auszuführen; Die gleichzeitige Änderung ist vorübergehend, und der Wiederholungsversuche wird in der Regel erfolgreich ausgeführt:
const int maxRetries = 3;
List<Blog> blogs;
for (var attempt = 0; attempt < maxRetries; attempt++)
{
try
{
blogs = await context.Blogs
.Include(b => b.Posts)
.AsSplitQuery()
.ToListAsync();
break;
}
catch (DbQueryConcurrencyException) when (attempt < maxRetries - 1)
{
// Retry on concurrent modification
}
}
Alternativ können Sie die geteilte Abfrage in eine serialisierbare oder Momentaufnahmetransaktion einschließen, um gleichzeitige Änderungen daran zu hindern, die Ergebnisse zu beeinflussen:
await using var transaction =
await context.Database.BeginTransactionAsync(IsolationLevel.Serializable);
var blogs = await context.Blogs
.Include(b => b.Posts)
.AsSplitQuery()
.ToListAsync();
await transaction.CommitAsync();
Wenn weder wiederholung noch eine Transaktion akzeptabel ist, wechseln Sie zu einer einzelnen Abfrage (AsSingleQuery()), die immer konsistent ist:
var blogs = await context.Blogs
.Include(b => b.Posts)
.AsSingleQuery()
.ToListAsync();
Microsoft.Data.Sqlite – Wichtige Änderungen
Hinweis
SQLitePCLRaw ist eine externe, von der Community verwaltete Bibliothek, die nicht im Besitz von Microsoft ist oder verwaltet wird. Microsoft. Data.Sqlite hängt davon für seine SQLite-Konnektivität ab.
Zusammenfassung
| Wichtige Änderung | Auswirkung |
|---|---|
| Microsoft. Data.Sqlite unterstützt .NET Framework nicht mehr | Mittelstufe |
| Einige SQLitePCLRaw-Bundlepakete werden nicht mehr verwaltet. | Mittelstufe |
| SQLite unterstützt UWP und klassische Xamarin nicht mehr | Niedrig |
Änderungen mit mittlerer Auswirkung
Microsoft. Data.Sqlite unterstützt .NET Framework nicht mehr
Altes Verhalten
Microsoft.Data.Sqlite Zuvor und Microsoft.Data.Sqlite.Core gezieltnetstandard2.0, die es ihnen ermöglichten, aus .NET Framework-Anwendungen verwendet zu werden.
Neues Verhalten
Microsoft.Data.Sqlite Ab 11.0 gilt net10.0 nur für beide Pakete. .NET Framework-Anwendungen können nicht mehr auf 11.0 verweisen oder verwendenMicrosoft.Data.Sqlite.
Warum
Das netstandard2.0 Ziel, das ältere, nicht unterstützte .NET Ziele angezeigt wird, wird unterstützt, und es wurden auch API-Unterschiede wie DateOnly z. B. und TimeOnly Unterstützung maskiert. Die Zielbestimmung für die mindestens unterstützte .NET Version macht die unterstützte Plattformoberfläche explizit klar.
Gegenmaßnahmen
Verschieben Sie die Anwendung nach Möglichkeit auf .NET 10 oder höher.
Wenn Sie auf .NET Framework bleiben müssen, bleiben Sie auf der neuesten Microsoft.Data.Sqlite 10.0.x-Wartungsversion. Die Zeile 10.0.x verwendetSQLitePCLRaw.bundle_e_sqlite3, sodass .NET Framework-Anwendungen die referenzierte SQLitePCLRaw.bundle_e_sqlite3 Version aktualisieren können, auch wenn Microsoft.Data.Sqlite keine Updates mehr empfangen werden.
Einige SQLitePCLRaw-Bundlepakete werden nicht mehr verwaltet.
Altes Verhalten
Zuvor haben die SQLitePCLRaw.bundle_e_sqlcipherPakete , SQLitePCLRaw.bundle_sqlite3, , SQLitePCLRaw.bundle_winsqlite3SQLitePCLRaw.bundle_greenund SQLitePCLRaw.bundle_e_sqlite3mc Pakete eine bequeme Möglichkeit zum Konfigurieren von SQLitePCLRaw mit dem entsprechenden SQLite-Anbieter bereitgestellt.
Neues Verhalten
Die SQLitePCLRaw.bundle_e_sqlcipherPakete , SQLitePCLRaw.bundle_sqlite3, , SQLitePCLRaw.bundle_winsqlite3SQLitePCLRaw.bundle_greenund SQLitePCLRaw.bundle_e_sqlite3mc Pakete werden vom SQLitePCLRaw-Betreuer nicht mehr aktualisiert. Sie sind nicht kompatibel mit SQLitePCLRaw.Core 3.0 und höher, sodass Anwendungen, die direkt auf eines dieser Pakete verweisen, zusammen mit SQLitePCLRaw.Core 3.x Konflikte auftreten. Anwendungen sollten zu den empfohlenen Alternativen migriert werden, um zukünftige Unterbrechungen zu vermeiden.
Warum
Der SQLitePCLRaw-Betreuer entfernte diese Bündel in Version 3.0; Jedes Bundle enthielt nur eine einzige Zeile konfigurationscode und zusätzlichen unnötigen Verpackungsaufwand, während die zugrunde liegenden Anbieterpakete weiterhin unterstützt werden. Das SQLitePCLRaw.bundle_e_sqlcipher Paket ist besonders betroffen: Es wurden verschlüsselungsfähige Builds bereitgestellt, die kaum verwaltet werden, was eine Sicherheitsbedenken für Verschlüsselungssoftware darstellt, bei denen Sicherheitsrisiken möglicherweise nicht gepatcht werden.
Gegenmaßnahmen
Bei Verwendung SQLitePCLRaw.bundle_e_sqlcipher (verschlüsselungsfähiges SQLite), migrieren Sie zu einer der folgenden Alternativen:
SQLite3 Multiple Ciphers: NuGet-Pakete sind über SQLite3MultipleCiphers-NuGet verfügbar. Referenz
Microsoft.Data.Sqlite.Corezusammen mitSQLite3MC.PCLRaw.bundle:<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="11.0.0" /> <PackageReference Include="SQLite3MC.PCLRaw.bundle" Version="2.x.x" />Konfigurieren Sie beim Verschlüsseln einer neuen Datenbank oder beim Öffnen einer vorhandenen Datenbank, die mit SQLCipher verschlüsselt wurde, das Chiffreschema mithilfe von URI-Parametern, z. B.:
Data Source=file:example.db?cipher=sqlcipher&legacy=4. Details finden Sie unter Wie eine vorhandene mit SQLCipher verschlüsselte Datenbank geöffnet wird .SQLite Encryption Extension (SEE): Die offizielle Verschlüsselungsimplementierung aus dem SQLite-Team. Eine kostenpflichtige Lizenz ist erforderlich. Sehen Sie https://sqlite.org/com/see.html sich den SQLite-Builddienst von SourceGear für NuGet-Optionen an.
SQLCipher: Kaufen Sie unterstützte Builds von Zetetic, oder erstellen Sie den Open Source Code selbst.
Wenn Sie das Paket verwenden SQLitePCLRaw.bundle_sqlite3 oder SQLitePCLRaw.bundle_winsqlite3, ersetzen Sie das Paket durch das entsprechende Anbieterpaket:
<!-- Old -->
<PackageReference Include="SQLitePCLRaw.bundle_sqlite3" Version="2.x.x" />
<!-- or -->
<PackageReference Include="SQLitePCLRaw.bundle_winsqlite3" Version="2.x.x" />
<!-- New -->
<PackageReference Include="SQLitePCLRaw.provider.sqlite3" Version="3.x.x" />
<!-- or -->
<PackageReference Include="SQLitePCLRaw.provider.winsqlite3" Version="3.x.x" />
Fügen Sie dann vor der Verwendung von SQLite explizite Initialisierung hinzu:
// For sqlite3
static void Init()
{
SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3());
}
// For winsqlite3
static void Init()
{
SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_winsqlite3());
}
Ersetzen Sie bei Verwendung SQLitePCLRaw.bundle_e_sqlite3mcdes Paketverweises durch SQLite3MC.PCLRaw.bundle:
<!-- Old -->
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3mc" Version="2.x.x" />
<!-- New -->
<PackageReference Include="SQLite3MC.PCLRaw.bundle" Version="2.x.x" />
Bei Verwendung SQLitePCLRaw.bundle_greenvon , wechseln Sie zu SQLitePCLRaw.bundle_e_sqlite3. Alternativ können Sie SQLitePCLRaw.config.e_sqlite3 ein separates systemeigenes Bibliothekspaket verwenden, z SourceGear.sqlite3. B. mit dem die SQLite-Version unabhängig aktualisiert werden kann:
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.x.x" />
Wenn Sie nur auf iOS abzielen und die System SQLite-Bibliothek verwenden möchten, verweisen Sie direkt auf den Anbieter, und initialisieren Sie ihn explizit:
<PackageReference Include="SQLitePCLRaw.Core" Version="3.x.x" />
<PackageReference Include="SQLitePCLRaw.provider.sqlite3" Version="3.x.x" />
static void Init()
{
SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3());
}
Weitere Informationen finden Sie unter SQLite-Verschlüsselungsoptionen für die Verwendung mit SQLitePCLRaw und SQLitePCLRaw 3.0 Versionshinweisen.
Änderungen mit geringer Auswirkung
SQLite unterstützt UWP und klassische Xamarin nicht mehr
Altes Verhalten
SQLitePCLRaw.bundle_e_sqlite3 Zuvor wurden native SQLite-Builds für Universelle Windows-Plattform (UWP) und klassische Xamarin (Xamarin.iOS, Xamarin) enthalten. Android und Xamarin. Mac) Ziele.
Neues Verhalten
SQLitePCLRaw.bundle_e_sqlite3 Ab 2.1.12 (auf 11.0 verwiesenMicrosoft.Data.Sqlite) sind systemeigene Builds für UWP und klassische Xamarin nicht mehr enthalten. Anwendungen, die auf diese Plattformen abzielen, können die gebündelte native SQLite-Bibliothek nicht mehr verwenden.
Warum
SQLite 3.53.0 (ausgeliefert von SQLitePCLRaw.bundle_e_sqlite3 2.1.12) unterstützt UWP und klassische Xamarin nicht mehr. Der SQLitePCLRaw-Betreuer hat diese Builds gelöscht, um mit neueren upstream-SQLite-Versionen auf dem Laufenden zu bleiben.
Gegenmaßnahmen
Migrieren Sie UWP-Anwendungen zu den Windows App SDK und klassischen Xamarin Anwendungen zu .NET MAUI, die auf modernen .NET unterstützt werden.
Wenn Sie auf UWP oder klassischen Xamarin bleiben müssen, bleiben Sie auf einer früheren Version davonSQLitePCLRaw.bundle_e_sqlite3, die weiterhin die nativen Builds für diese Plattformen enthält.