Breaking Changes in EF Core 3.0Breaking changes included in EF Core 3.0

Die folgenden API-Änderungen und Behavior Changes können dazu führen, dass vorhandene Anwendungen beim Upgrade auf 3.0.0 nicht mehr funktionieren.The following API and behavior changes have the potential to break existing applications when upgrading them to 3.0.0. Änderungen, die sich voraussichtlich nur auf Datenbankanbieter auswirken, sind unter Änderungen mit Auswirkungen auf den Anbieter dokumentiert.Changes that we expect to only impact database providers are documented under provider changes.

ZusammenfassungSummary

Wichtige ÄnderungBreaking change AuswirkungImpact
LINQ-Abfragen werden nicht mehr auf dem Client ausgewertetLINQ queries are no longer evaluated on the client HochHigh
EF Core 3.0 zielt auf .NET Standard 2.1 und nicht auf .NET Standard 2.0 abEF Core 3.0 targets .NET Standard 2.1 rather than .NET Standard 2.0 HochHigh
Das EF Core-Befehlszeilentool (dotnet ef) ist nicht mehr Bestandteil des .NET Core SDKThe EF Core command-line tool, dotnet ef, is no longer part of the .NET Core SDK HochHigh
DetectChanges berücksichtigt vom Speicher generierte SchlüsselwerteDetectChanges honors store-generated key values HochHigh
FromSql, ExecuteSql und ExecuteSqlAsync wurden umbenanntFromSql, ExecuteSql, and ExecuteSqlAsync have been renamed HochHigh
Abfragetypen werden mit Entitätstypen zusammengeführtQuery types are consolidated with entity types HochHigh
Entity Framework Core ist nicht mehr Bestandteil des gemeinsam verwendeten ASP.NET Core-FrameworksEntity Framework Core is no longer part of the ASP.NET Core shared framework MittelMedium
Kaskadierende DELETE-Anweisungen werden standardmäßig sofort ausgeführtCascade deletions now happen immediately by default MittelMedium
Eager Loading von verwandten Entitäten erfolgt nun in einer einzelnen AbfrageEager loading of related entities now happens in a single query MittelMedium
DeleteBehavior.Restrict verfügt über eine übersichtlichere SemantikDeleteBehavior.Restrict has cleaner semantics MittelMedium
Die Konfigurations-API für Beziehungen abhängiger (owned) Typen wurde geändertConfiguration API for owned type relationships has changed MittelMedium
Für jede Eigenschaft wird separat ein ganzzahliger speicherinterner Schlüssel generiertEach property uses independent in-memory integer key generation MittelMedium
Abfragen ohne Nachverfolgung führen keine Identitätsauflösung mehr durchNo-tracking queries no longer perform identity resolution MittelMedium
Metadaten-API-ÄnderungenMetadata API changes MittelMedium
Anbieterspezifische Metadaten-API-ÄnderungenProvider-specific Metadata API changes MittelMedium
UseRowNumberForPaging wurde entferntUseRowNumberForPaging has been removed MittelMedium
FromSql-Methode kann nicht zusammengesetzt werden, wenn sie mit einer gespeicherten Prozedur verwendet wirdFromSql method when used with stored procedure cannot be composed MittelMedium
FromSql-Methoden können nur für die Stammelemente der Abfrage angegeben werdenFromSql methods can only be specified on query roots NiedrigLow
Die Abfrageausführung wird auf Debugebene protokolliert – zurückgesetztQuery execution is logged at Debug level Reverted NiedrigLow
Temporäre Schlüsselwerte werden nicht mehr Entitätsinstanzen zugewiesenTemporary key values are no longer set onto entity instances NiedrigLow
Abhängige Entitäten, die die Tabelle gemeinsam mit dem Prinzipal verwenden, sind jetzt optionalDependent entities sharing the table with the principal are now optional NiedrigLow
Alle Entitäten, die eine Tabelle mit einer Spalte für das Parallelitätstoken gemeinsam verwenden, müssen diese einer Eigenschaft zuordnenAll entities sharing a table with a concurrency token column have to map it to a property NiedrigLow
Geerbte Eigenschaften von nicht zugeordneten Typen sind nun einer einzelnen Spalte für alle abgeleiteten Typen zugeordnetInherited properties from unmapped types are now mapped to a single column for all derived types NiedrigLow
Die Konvention zur Fremdschlüsseleigenschaft entspricht nicht mehr dem Namen der PrinzipaleigenschaftThe foreign key property convention no longer matches same name as the principal property NiedrigLow
Die Datenbankverbindung wird jetzt getrennt, wenn sie nicht mehr verwendet wird, bevor TransactionScope abgeschlossen wurdeDatabase connection is now closed if not used anymore before the TransactionScope has been completed NiedrigLow
Unterstützungsfelder werden standardmäßig verwendetBacking fields are used by default NiedrigLow
Eine Ausnahme wird ausgelöst, wenn mehrere kompatible Unterstützungsfelder gefunden werdenThrow if multiple compatible backing fields are found NiedrigLow
„Nur-Feld“-Eigenschaftennamen sollten dem Feldnamen entsprechenField-only property names should match the field name NiedrigLow
AddLogging und AddMemoryCache werden nicht mehr von AddDbContext/AddDbContextPool aufgerufenAddDbContext/AddDbContextPool no longer call AddLogging and AddMemoryCache NiedrigLow
DbContext.Entry erkennt nun mit DetectChanges lokale ÄnderungenDbContext.Entry now performs a local DetectChanges NiedrigLow
Schlüssel aus Zeichenfolgen und Bytearrays werden standardmäßig nicht vom Client generiertString and byte array keys are not client-generated by default NiedrigLow
ILoggerFactory ist nun ein bereichsbezogener DienstILoggerFactory is now a scoped service NiedrigLow
Für Proxys mit Lazy Loading (trägem Laden) gilt nicht mehr die Annahme, dass Navigationseigenschaften vollständig geladen sindLazy-loading proxies no longer assume navigation properties are fully loaded NiedrigLow
Die Erstellung zu vieler interner Dienstanbieter führt standardmäßig zu einem FehlerExcessive creation of internal service providers is now an error by default NiedrigLow
Neues Verhalten für HasOne/HasMany bei Aufruf mit einer einzelnen ZeichenfolgeNew behavior for HasOne/HasMany called with a single string NiedrigLow
Der Rückgabetyp für mehrere asynchrone Methoden wurde von Task in ValueTask geändertThe return type for several async methods has been changed from Task to ValueTask NiedrigLow
Die Anmerkung Relational:TypeMapping heißt nun nur noch TypeMappingThe Relational:TypeMapping annotation is now just TypeMapping NiedrigLow
ToTable löst für einen abgeleiteten Typ eine Ausnahme ausToTable on a derived type throws an exception NiedrigLow
EF Core sendet keine PRAGMA-Anweisungen mehr, um Fremdschlüssel in SQLite zu erzwingenEF Core no longer sends pragma for SQLite FK enforcement NiedrigLow
SQLitePCLRaw.bundle_e_sqlite3 ist nun eine Abhängigkeit von Microsoft.EntityFrameworkCore.SqliteMicrosoft.EntityFrameworkCore.Sqlite now depends on SQLitePCLRaw.bundle_e_sqlite3 NiedrigLow
GUID-Werte werden jetzt als TEXT in SQLite gespeichertGuid values are now stored as TEXT on SQLite NiedrigLow
Char-Werte werden jetzt als TEXT in SQLite gespeichertChar values are now stored as TEXT on SQLite NiedrigLow
Migrations-IDs werden jetzt mit dem Kalender der invarianten Kultur generiertMigration IDs are now generated using the invariant culture's calendar NiedrigLow
Erweiterungsinformationen und -metadaten wurden aus IDbContextOptionsExtension entferntExtension info/metadata has been removed from IDbContextOptionsExtension NiedrigLow
LogQueryPossibleExceptionWithAggregateOperator wurde umbenanntLogQueryPossibleExceptionWithAggregateOperator has been renamed NiedrigLow
Übersichtlichere API für Namen von FremdschlüsselconstraintsClarify API for foreign key constraint names NiedrigLow
IRelationalDatabaseCreator.HasTables/HasTablesAsync ist jetzt öffentlichIRelationalDatabaseCreator.HasTables/HasTablesAsync have been made public NiedrigLow
Microsoft.EntityFrameworkCore.Design ist jetzt ein DevelopmentDependency-PaketMicrosoft.EntityFrameworkCore.Design is now a DevelopmentDependency package NiedrigLow
SQLitePCL.raw wurde auf Version 2.0.0 aktualisiertSQLitePCL.raw updated to version 2.0.0 NiedrigLow
NetTopologySuite wurde auf Version 2.0.0 aktualisiertNetTopologySuite updated to version 2.0.0 NiedrigLow
Microsoft.Data.SqlClient wird statt System.Data.SqlClient verwendetMicrosoft.Data.SqlClient is used instead of System.Data.SqlClient NiedrigLow
Beziehungen mit mehreren mehrdeutigen Selbstverweisen müssen nun konfiguriert werdenMultiple ambiguous self-referencing relationships must be configured NiedrigLow
DbFunction.Schema ist NULL oder eine leere Zeichenfolge und ist deshalb so konfiguriert, dass es im Standardschema des Modells istDbFunction.Schema being null or empty string configures it to be in model's default schema NiedrigLow

LINQ-Abfragen werden nicht mehr auf dem Client ausgewertetLINQ queries are no longer evaluated on the client

Issue #14935 Siehe auch Issue #12795Tracking Issue #14935 Also see issue #12795

Altes VerhaltenOld behavior

Vor Version 3.0 wurden in EF Core automatisch Ausdrücke auf dem Client ausgewertet, wenn diese Teil einer Abfrage waren und nicht in SQL oder in einen Parameter konvertiert werden konnten.Before 3.0, when EF Core couldn't convert an expression that was part of a query to either SQL or a parameter, it automatically evaluated the expression on the client. Wenn potenziell aufwendige Ausdrücke auf dem Client ausgewertet werden sollten, wurde standardmäßig nur eine Warnung ausgelöst.By default, client evaluation of potentially expensive expressions only triggered a warning.

Neues VerhaltenNew behavior

Ab Version 3.0 können in EF Core nur Ausdrücke der obersten Projektion (dem letzten Select()-Aufruf in der Abfrage) auf dem Client ausgewertet werden.Starting with 3.0, EF Core only allows expressions in the top-level projection (the last Select() call in the query) to be evaluated on the client. Wenn Ausdrücke in einem anderen Teil der Abfrage nicht in SQL oder in einen Parameter konvertiert werden können, wird eine Ausnahme ausgelöst.When expressions in any other part of the query can't be converted to either SQL or a parameter, an exception is thrown.

HintergründeWhy

Die automatische Auswertung von Abfragen auf Clients hat zur Folge, dass viele Abfragen auch dann ausgeführt werden, wenn wichtige Teile nicht übersetzt werden können.Automatic client evaluation of queries allows many queries to be executed even if important parts of them can't be translated. Dieses Verhalten kann zu unerwartetem und potenziell schädlichem Verhalten führen, das möglicherweise erst in der Produktionsphase erkannt wird.This behavior can result in unexpected and potentially damaging behavior that may only become evident in production. Eine nicht übersetzbare Bedingung in einem Where()-Aufruf kann sich beispielsweise so auswirken, dass alle Zeilen einer Tabelle vom Datenbankserver übertragen werden und der Filter auf dem Client angewendet wird.For example, a condition in a Where() call which can't be translated can cause all rows from the table to be transferred from the database server, and the filter to be applied on the client. Wenn die Tabelle in der Entwicklungsphase nur wenige Zeilen enthält, ist es gut möglich, dass diese Situation unerkannt bleibt. Wenn die Anwendung jedoch in die Produktionsumgebung überführt wird, enthält die Tabelle möglicherweise Millionen von Zeilen, was zu schwerwiegenden Konsequenzen führen kann.This situation can easily go undetected if the table contains only a few rows in development, but hit hard when the application moves to production, where the table may contain millions of rows. Wie die Erfahrung in der Entwicklungsphase gezeigt hat, können auch Warnungen, die bei Auswertungen auf dem Client ausgelöst werden, dieses Problem nicht lösen, da sie sich leicht ignorieren lassen.Client evaluation warnings also proved too easy to ignore during development.

Die automatische Auswertung auf Clients kann darüber hinaus zu Problemen führen, bei denen die Verbesserung der Abfrageübersetzung für bestimmte Ausdrücke zu unbeabsichtigten Breaking Changes zwischen Releases führt.Besides this, automatic client evaluation can lead to issues in which improving query translation for specific expressions caused unintended breaking changes between releases.

Vorbeugende MaßnahmenMitigations

Wenn sich eine Abfrage nicht vollständig übersetzen lässt, habe Sie zwei Möglichkeiten: Schreiben Sie sie entweder um, oder setzen Sie alternativ AsEnumerable(), ToList() oder ähnliche Methoden ein, um Daten wieder zurück an den Client zu übertragen, wo sie mit LINQ to Objects weiterverarbeitet werden können.If a query can't be fully translated, then either rewrite the query in a form that can be translated, or use AsEnumerable(), ToList(), or similar to explicitly bring data back to the client where it can then be further processed using LINQ-to-Objects.

EF Core 3.0 zielt auf .NET Standard 2.1 und nicht auf .NET Standard 2.0 abEF Core 3.0 targets .NET Standard 2.1 rather than .NET Standard 2.0

Issue #15498Tracking Issue #15498

Altes VerhaltenOld behavior

Vor 3.0 zielte EF Core auf .NET Standard 2.0 ab und wurde auf allen Plattformen ausgeführt, die diesen Standard unterstützen, einschließlich .NET Framework.Before 3.0, EF Core targeted .NET Standard 2.0 and would run on all platforms that support that standard, including .NET Framework.

Neues VerhaltenNew behavior

Ab 3.0 zielt EF Core auf .NET Standard 2.1 ab und wird auf allen Plattformen ausgeführt, die diesen Standard unterstützen.Starting with 3.0, EF Core targets .NET Standard 2.1 and will run on all platforms that support this standard. Dies schließt .NET Framework nicht ein.This does not include .NET Framework.

HintergründeWhy

Dies ist ein Teil der strategischen Entscheidung bezüglich .NET-Technologien, um den Fokus auf .NET Core und andere moderne .NET-Plattformen (z. B. Xamarin) zu legen.This is part of a strategic decision across .NET technologies to focus energy on .NET Core and other modern .NET platforms, such as Xamarin.

Vorbeugende MaßnahmenMitigations

Erwägen Sie, zu einer moderneren .NET-Plattform zu wechseln.Consider moving to a modern .NET platform. Falls dies nicht möglich ist, verwenden Sie weiterhin EF Core 2.1 oder EF Core 2.2, die beide .NET Framework unterstützen.If this is not possible, then continue to use EF Core 2.1 or EF Core 2.2, both of which support .NET Framework.

Entity Framework Core ist nicht mehr Teil des gemeinsam verwendeten ASP.NET Core-FrameworksEntity Framework Core is no longer part of the ASP.NET Core shared framework

Issueankündigungen #325Tracking Issue Announcements#325

Altes VerhaltenOld behavior

Vor Version 3.0 von ASP.NET Core wurden EF Core und einige der zugehörigen Datenanbieter wie SQL Server eingeschlossen, wenn Microsoft.AspNetCore.App oder Microsoft.AspNetCore.All ein Paketverweis hinzugefügt wurde.Before ASP.NET Core 3.0, when you added a package reference to Microsoft.AspNetCore.App or Microsoft.AspNetCore.All, it would include EF Core and some of the EF Core data providers like the SQL Server provider.

Neues VerhaltenNew behavior

Ab Version 3.0 enthält das gemeinsam verwendete ASP.NET Core-Framework weder EF Core noch zugehörige Datenanbieter.Starting in 3.0, the ASP.NET Core shared framework doesn't include EF Core or any EF Core data providers.

HintergründeWhy

Vor dieser Änderung konnte EF Core auf unterschiedliche Arten bezogen werden. Diese richteten sich danach, ob ASP.NET Core und SQL Server oder ein anderes Zielframework für die Anwendung vorgesehen war.Before this change, getting EF Core required different steps depending on whether the application targeted ASP.NET Core and SQL Server or not. Bei einem Upgrade von ASP.NET Core wurde zudem ein Upgrade von EF Core und des SQL Server-Anbieters erzwungen, was nicht in allen Fällen gewünscht war.Also, upgrading ASP.NET Core forced the upgrade of EF Core and the SQL Server provider, which isn't always desirable.

Durch die eingeführte Änderung wird EF Core unter allen Anbietern, unterstützten .NET-Implementierungen und Anwendungstypen auf dieselbe Weise bezogen.With this change, the experience of getting EF Core is the same across all providers, supported .NET implementations and application types. Entwickler können nun außerdem genau festlegen, wann für EF Core und zugehörige Datenanbieter ein Upgrade durchgeführt werden soll.Developers can also now control exactly when EF Core and EF Core data providers are upgraded.

Vorbeugende MaßnahmenMitigations

Wenn Sie EF Core in einer Anwendung unter ASP.NET Core 3.0 oder in einer anderen unterstützten Anwendung verwenden möchten, müssen Sie dem EF Core-Datenbankanbieter, der für die Anwendung genutzt werden soll, explizit einen Paketverweis hinzufügen.To use EF Core in an ASP.NET Core 3.0 application or any other supported application, explicitly add a package reference to the EF Core database provider that your application will use.

Das EF Core-Befehlszeilentool (dotnet ef) ist nicht länger Bestandteil des .NET Core SDK.The EF Core command-line tool, dotnet ef, is no longer part of the .NET Core SDK

Issue #14016Tracking Issue #14016

Altes VerhaltenOld behavior

Vor Version 3.0 war das dotnet ef-Tool im .NET Core SDK enthalten und konnte von der Befehlszeile aus ohne zusätzliche Schritte in einem beliebigen Projekt verwendet werden.Before 3.0, the dotnet ef tool was included in the .NET Core SDK and was readily available to use from the command line from any project without requiring extra steps.

Neues VerhaltenNew behavior

Ab Version 3.0 ist das dotnet ef-Tool nicht mehr im .NET SDK enthalten und muss deshalb vor der Verwendung explizit als lokales oder globales Tool installiert werden.Starting in 3.0, the .NET SDK does not include the dotnet ef tool, so before you can use it you have to explicitly install it as a local or global tool.

HintergründeWhy

Durch diese Änderung kann dotnet ef als reguläres .NET-CLI-Tool für NuGet verteilt und aktualisiert werden und entspricht damit dem üblichen Verfahren, dass EF Core 3.0 ebenfalls immer als NuGet-Paket verteilt wird.This change allows us to distribute and update dotnet ef as a regular .NET CLI tool on NuGet, consistent with the fact that the EF Core 3.0 is also always distributed as a NuGet package.

Vorbeugende MaßnahmenMitigations

Um Migrationen zu verwalten oder ein Gerüst für DbContext zu erstellen, installieren Sie dotnet-ef als globales Tool:To be able to manage migrations or scaffold a DbContext, install dotnet-ef as a global tool:

  $ dotnet tool install --global dotnet-ef

Eine Verwendung als lokales Tool ist ebenfalls möglich, wenn Sie die Abhängigkeiten eines Projekts wiederherstellen, das das Tool mithilfe einer Toolmanifestdatei als Toolabhängigkeit deklariert.You can also obtain it a local tool when you restore the dependencies of a project that declares it as a tooling dependency using a tool manifest file.

FromSql, ExecuteSql und ExecuteSqlAsync wurden umbenanntFromSql, ExecuteSql, and ExecuteSqlAsync have been renamed

Issue #10996Tracking Issue #10996

Altes VerhaltenOld behavior

Vor Version 3.0 wurden in EF Core diese Methodennamen überladen, um entweder mit einer normalen Zeichenfolge oder einer Zeichenfolge, die in SQL und Parameter interpoliert werden sollte, zu arbeiten.Before EF Core 3.0, these method names were overloaded to work with either a normal string or a string that should be interpolated into SQL and parameters.

Neues VerhaltenNew behavior

Ab Version 3.0 verwenden Sie in EF Core FromSqlRaw, ExecuteSqlRaw und ExecuteSqlRawAsync, um eine parametrisierte Abfrage zu erstellen, bei der die Parameter einzeln aus der Abfragezeichenfolge übergeben werden.Starting with EF Core 3.0, use FromSqlRaw, ExecuteSqlRaw, and ExecuteSqlRawAsync to create a parameterized query where the parameters are passed separately from the query string. Beispiel:For example:

context.Products.FromSqlRaw(
    "SELECT * FROM Products WHERE Name = {0}",
    product.Name);

Verwenden Sie FromSqlInterpolated, ExecuteSqlInterpolated und ExecuteSqlInterpolatedAsync, um eine parametrisierte Abfrage zu erstellen, bei der die Parameter als Teil einer interpolierten Abfragezeichenfolge übergeben werden.Use FromSqlInterpolated, ExecuteSqlInterpolated, and ExecuteSqlInterpolatedAsync to create a parameterized query where the parameters are passed as part of an interpolated query string. Beispiel:For example:

context.Products.FromSqlInterpolated(
    $"SELECT * FROM Products WHERE Name = {product.Name}");

Beachten Sie, dass die beiden oben genannten Abfragen dieselbe parametrisierte SQL mit denselben SQL-Parametern erzeugen.Note that both of the queries above will produce the same parameterized SQL with the same SQL parameters.

HintergründeWhy

Bei Methodenüberladungen wie dieser wird sehr leicht versehentlich die Methode für unformatierte Zeichenfolgen aufgerufen, wenn eigentlich beabsichtigt war, die Methode für interpolierte Zeichenfolgen aufzurufen (und umgekehrt).Method overloads like this make it very easy to accidentally call the raw string method when the intent was to call the interpolated string method, and the other way around. Dadurch werden Abfragen möglicherweise nicht parametrisiert, obwohl dies der Fall sein sollte.This could result in queries not being parameterized when they should have been.

Vorbeugende MaßnahmenMitigations

Verwenden Sie ab sofort die neuen Methodennamen.Switch to use the new method names.

FromSql-Methode kann nicht zusammengesetzt werden, wenn sie mit einer gespeicherten Prozedur verwendet wirdFromSql method when used with stored procedure cannot be composed

Issue #15392Tracking Issue #15392

Altes VerhaltenOld behavior

Vor EF Core 3.0 versuchte die FromSql-Methode, zu ermitteln, ob das übergebene SQL zusammengesetzt werden konnte.Before EF Core 3.0, FromSql method tried to detect if the passed SQL can be composed upon. Eine Clientauswertung wurde durchgeführt, wenn das SQL wie eine gespeicherte Prozedur nicht zusammensetzbar war.It did client evaluation when the SQL was non-composable like a stored procedure. Die folgende Abfrage funktionierte, indem die gespeicherte Prozedur auf dem Server und die FirstOrDefault-Methode auf dem Client ausgeführt wurde.The following query worked by running the stored procedure on the server and doing FirstOrDefault on the client side.

context.Products.FromSqlRaw("[dbo].[Ten Most Expensive Products]").FirstOrDefault();

Neues VerhaltenNew behavior

Ab EF Core 3.0 versucht EF Core nicht mehr, das SQL zu analysieren.Starting with EF Core 3.0, EF Core will not try to parse the SQL. Wenn Sie also nach FromSqlRaw/FromSqlInterpolated zusammensetzen, setzt EF Core das SQL zusammen, indem eine Unterabfrage ausgelöst wird.So if you are composing after FromSqlRaw/FromSqlInterpolated, then EF Core will compose the SQL by causing sub query. Wenn Sie eine gespeicherte Prozedur mit Zusammensetzung verwenden, wird eine Ausnahme für ungültige SQL-Syntax ausgelöst.So if you are using a stored procedure with composition then you will get an exception for invalid SQL syntax.

HintergründeWhy

EF Core 3.0 unterstützt die automatische Clientauswertung nicht, da diese wie hier erläutert fehleranfällig war.EF Core 3.0 does not support automatic client evaluation, since it was error prone as explained here.

LösungMitigation

Wenn Sie eine gespeicherte Prozedur in FromSqlRaw/FromSqlInterpolated verwenden, wissen Sie, dass diese nicht zusammengesetzt werden kann. Daher können Sie AsEnumerable/AsAsyncEnumerable direkt nach dem FromSql-Methodenaufruf hinzufügen, um die Zusammensetzung auf dem Server zu vermeiden.If you are using a stored procedure in FromSqlRaw/FromSqlInterpolated, you know that it cannot be composed upon, so you can add AsEnumerable/AsAsyncEnumerable right after the FromSql method call to avoid any composition on server side.

context.Products.FromSqlRaw("[dbo].[Ten Most Expensive Products]").AsEnumerable().FirstOrDefault();

FromSql-Methoden können nur für die Stammelemente der Abfrage angegeben werden.FromSql methods can only be specified on query roots

Issue #15704Tracking Issue #15704

Altes VerhaltenOld behavior

Vor EF Core 3.0 konnte die FromSql-Methode an einer beliebigen Stelle in der Abfrage angegeben werden.Before EF Core 3.0, the FromSql method could be specified anywhere in the query.

Neues VerhaltenNew behavior

Ab EF Core 3.0 können die neuen Methoden FromSqlRaw und FromSqlInterpolated (durch die FromSql ersetzt wird) nur für Stammelemente von Abfragen angegeben werden, d.h. direkt für das DbSet<>.Starting with EF Core 3.0, the new FromSqlRaw and FromSqlInterpolated methods (which replace FromSql) can only be specified on query roots, i.e. directly on the DbSet<>. Der Versuch, sie an anderer Stelle anzugeben, führt zu einem Kompilierungsfehler.Attempting to specify them anywhere else will result in a compilation error.

HintergründeWhy

Die Angabe von FromSql an einer anderen Stelle als für ein DbSet erbrachte keine zusätzliche Bedeutung und keinen Mehrwert, sondern konnte in bestimmten Szenarien zu Mehrdeutigkeiten führen.Specifying FromSql anywhere other than on a DbSet had no added meaning or added value, and could cause ambiguity in certain scenarios.

Vorbeugende MaßnahmenMitigations

FromSql Aufrufe sollten so verschoben, dass sie direkt für das zugehörige DbSet gelten.FromSql invocations should be moved to be directly on the DbSet to which they apply.

Abfragen ohne Nachverfolgung führen keine Identitätsauflösung mehr durchNo-tracking queries no longer perform identity resolution

Issue #13518Tracking Issue #13518

Altes VerhaltenOld behavior

Vor EF Core 3.0 wurde dieselbe Entitätsinstanz für jedes Vorkommen einer Entität mit einem bestimmten Typ und einer bestimmten ID verwendet.Before EF Core 3.0, the same entity instance would be used for every occurrence of an entity with a given type and ID. Dies entspricht dem Verhalten von Abfragen zu Nachverfolgungen.This matches the behavior of tracking queries. Die folgende Abfrage:For example, this query:

var results = context.Products.Include(e => e.Category).AsNoTracking().ToList();

gibt dieselbe Category-Instanz für jedes Product zurück, das der bestimmten Kategorie zugeordnet ist.would return the same Category instance for each Product that is associated with the given category.

Neues VerhaltenNew behavior

Ab EF Core 3.0 werden unterschiedliche Entitätsinstanzen erstellt, wenn eine Entität mit einem bestimmten Typ und einer bestimmten ID an verschiedenen Stellen im zurückgegebenen Diagramm gefunden wird.Starting with EF Core 3.0, different entity instances will be created when an entity with a given type and ID is encountered at different places in the returned graph. Die Abfrage oben gibt beispielsweise nun eine neue Category-Instanz für jedes Product zurück, auch wenn zwei Produkte derselben Kategorie zugeordnet sind.For example, the query above will now return a new Category instance for each Product even when two products are associated with the same category.

HintergründeWhy

Die Identitätsauflösung (d. h. Feststellen, dass eine Entität über denselben Typ und die dieselbe ID wie die zuvor aufgetretene Entität verfügt) fügt zusätzlichen Aufwand für Leistung und Arbeitsspeicher hinzu.Identity resolution (that is, determining that an entity has the same type and ID as a previously encountered entity) adds additional performance and memory overhead. Dies widerspricht normalerweise dem Grund, warum in erster Linie Abfragen ohne Nachverfolgung verwendet werden.This usually runs counter to why no-tracking queries are used in the first place. Obwohl die Identitätsauflösung manchmal nützlich sein kann, wird sie nicht benötigt, wenn die Entitäten serialisiert und an den Client gesendet werden, was manchmal für Abfragen ohne Nachverfolgung der Fall ist.Also, while identity resolution can sometimes be useful, it is not needed if the entities are to be serialized and sent to a client, which is common for no-tracking queries.

Vorbeugende MaßnahmenMitigations

Verwenden Sie eine Nachverfolgungsabfrage, falls die Auflösung erforderlich ist.Use a tracking query if identity resolution is required.

Die Abfrageausführung wird auf Debugebene protokolliert – zurückgesetztQuery execution is logged at Debug level Reverted

Issue #14523Tracking Issue #14523

Wir haben diese Änderung zurückgesetzt, weil die neue Konfiguration in EF Core 3.0 die Angabe des Protokolliergrads für jedes Ereignis durch die Anwendung ermöglicht.We reverted this change because new configuration in EF Core 3.0 allows the log level for any event to be specified by the application. Um z.B. die Protokollierung von SQL zu Debug zu ändern, konfigurieren Sie den Grad explizit in OnConfiguring oder AddDbContext:For example, to switch logging of SQL to Debug, explicitly configure the level in OnConfiguring or AddDbContext:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlServer(connectionString)
        .ConfigureWarnings(c => c.Log((RelationalEventId.CommandExecuting, LogLevel.Debug)));

Temporäre Schlüsselwerte werden nicht mehr Entitätsinstanzen zugewiesenTemporary key values are no longer set onto entity instances

Issue #12378Tracking Issue #12378

Altes VerhaltenOld behavior

Vor Version 3.0 wurden in EF Core allen Schlüsseleigenschaften temporäre Werte zugewiesen. Später wurden den Eigenschaften dann die tatsächlichen Werte zugewiesen, die von der Datenbank generiert wurden.Before EF Core 3.0, temporary values were assigned to all key properties that would later have a real value generated by the database. Die temporären Werte waren in der Regel große negative Zahlen.Usually these temporary values were large negative numbers.

Neues VerhaltenNew behavior

Ab Version 3.0 wird in EF Core der temporäre Wert als Teil der Überwachungsinformationen der Entität gespeichert. Die Schlüsseleigenschaft selbst bleibt unverändert.Starting with 3.0, EF Core stores the temporary key value as part of the entity's tracking information, and leaves the key property itself unchanged.

HintergründeWhy

Diese Änderung wurde vorgenommen, damit temporäre Schlüsselwerte nicht fälschlicherweise dauerhaft gespeichert werden, wenn eine Entität, die vorher von einer DbContext-Instanz überwacht wurde, in eine andere DbContext-Instanz verschoben wird.This change was made to prevent temporary key values from erroneously becoming permanent when an entity that has been previously tracked by some DbContext instance is moved to a different DbContext instance.

Vorbeugende MaßnahmenMitigations

Anwendungen, die Primärschlüsselwerte Fremdschlüsseln zuweisen, um Zuordnungen zwischen Entitäten zu erstellen, können vom alten Verhalten abhängig sein, wenn Primärschlüssel vom Speicher generiert werden und zu Entitäten im Added-Zustand gehören.Applications that assign primary key values onto foreign keys to form associations between entities may depend on the old behavior if the primary keys are store-generated and belong to entities in the Added state. Sie können dies wie folgt vermeiden:This can be avoided by:

  • Verwenden Sie keine vom Speicher generierten Schlüssel.Not using store-generated keys.
  • Legen Sie zum Erstellen von Zuordnungen keine Fremdschlüsselwerte, sondern Navigationseigenschaften fest.Setting navigation properties to form relationships instead of setting foreign key values.
  • Rufen Sie die tatsächlichen temporären Schlüsselwerte aus den Überwachungsinformationen der Entität ab.Obtain the actual temporary key values from the entity's tracking information. context.Entry(blog).Property(e => e.Id).CurrentValue gibt beispielsweise den temporären Wert zurück, obwohl blog.Id noch nicht festgelegt wurde.For example, context.Entry(blog).Property(e => e.Id).CurrentValue will return the temporary value even though blog.Id itself hasn't been set.

DetectChanges berücksichtigt vom Speicher generierte SchlüsselwerteDetectChanges honors store-generated key values

Issue #14616Tracking Issue #14616

Altes VerhaltenOld behavior

Vor Version 3.0 wurde in EF Core eine nicht überwachte Entität, die von DetectChanges gefunden wurde, im Added-Zustand überwacht und als neue Zeile eingefügt, sobald SaveChanges aufgerufen wurde.Before EF Core 3.0, an untracked entity found by DetectChanges would be tracked in the Added state and inserted as a new row when SaveChanges is called.

Neues VerhaltenNew behavior

Ab Version 3.0 wird in EF Core die Entität im Modified-Zustand überwacht, wenn für diese generierte Schlüsselwerte verwendet werden und ein Schlüsselwert festgelegt wird.Starting with EF Core 3.0, if an entity is using generated key values and some key value is set, then the entity will be tracked in the Modified state. Es wird also davon ausgegangen, dass eine Zeile für die Entität vorhanden ist. Wenn SaveChanges aufgerufen wird, wird die Zeile außerdem aktualisiert.This means that a row for the entity is assumed to exist and it will be updated when SaveChanges is called. Falls kein Schlüsselwert festgelegt ist oder der Entitätstyp keine generierten Schlüssel verwendet, wird die neue Entität wie in früheren Version weiterhin im Added-Zustand überwacht.If the key value isn't set, or if the entity type isn't using generated keys, then the new entity will still be tracked as Added as in previous versions.

HintergründeWhy

Diese Änderung wurde vorgenommen, um bei der Verwendung von speichergenerierten Schlüsseln die Arbeit mit nicht verbundenen Entitätsgraphen einfacher und konsistenter zu gestalten.This change was made to make it easier and more consistent to work with disconnected entity graphs while using store-generated keys.

Vorbeugende MaßnahmenMitigations

Diese Änderung kann dazu führen, dass eine Anwendung nicht mehr funktioniert. Dieser Fall tritt ein, wenn für Entitätstypen generierte Schlüssel vorgesehen sind, dann jedoch explizit Schlüsselwerte für neue Instanzen festgelegt werden.This change can break an application if an entity type is configured to use generated keys but key values are explicitly set for new instances. Sie können dieses Problem vermeiden, indem Sie explizit festlegen, dass für Schlüsseleigenschaften keine generierten Werte verwendet werden sollen.The fix is to explicitly configure the key properties to not use generated values. Dies ist beispielsweise mit der Fluent-API möglich:For example, with the fluent API:

modelBuilder
    .Entity<Blog>()
    .Property(e => e.Id)
    .ValueGeneratedNever();

Alternativ bieten sich auch Datenanmerkungen an:Or with data annotations:

[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string Id { get; set; }

Kaskadierende Deletes werden standardmäßig sofort ausgeführtCascade deletions now happen immediately by default

Issue #10114Tracking Issue #10114

Altes VerhaltenOld behavior

Vor Version 3.0 wurden in EF Core kaskadierenden Aktionen (Löschen von abhängigen Entitäten nach dem Löschen eines erforderlichen Prinzipals oder nach dem Aufheben einer Beziehung zum erforderlichen Prinzipal) erst ausgeführt, wenn SaveChanges aufgerufen wurde.Before 3.0, EF Core applied cascading actions (deleting dependent entities when a required principal is deleted or when the relationship to a required principal is severed) did not happen until SaveChanges was called.

Neues VerhaltenNew behavior

Ab Version 3.0 werden in EF Core kaskadierende Aktionen angewendet, sobald die auslösende Bedingung erkannt wird.Starting with 3.0, EF Core applies cascading actions as soon as the triggering condition is detected. Wenn beispielsweise context.Remove() zum Löschen einer Prinzipalentität aufgerufen wird, führt das dazu, dass auch alle zugehörigen erforderlichen Entitäten, die überwacht werden, sofort auf Deleted festgelegt werden.For example, calling context.Remove() to delete a principal entity will result in all tracked related required dependents also being set to Deleted immediately.

HintergründeWhy

Diese Änderung wurde vorgenommen, um die Arbeit mit Datenbindungen und Überwachungsszenarios zu vereinfachen, in denen bekannt sein muss, welche Entitäten vor dem Aufruf von SaveChanges gelöscht werden.This change was made to improve the experience for data binding and auditing scenarios where it is important to understand which entities will be deleted before SaveChanges is called.

Vorbeugende MaßnahmenMitigations

Sie können das vorherige Verhalten wiederherstellen, indem Sie für context.ChangedTracker die entsprechenden Einstellungen vornehmen.The previous behavior can be restored through settings on context.ChangedTracker. Beispiel:For example:

context.ChangeTracker.CascadeDeleteTiming = CascadeTiming.OnSaveChanges;
context.ChangeTracker.DeleteOrphansTiming = CascadeTiming.OnSaveChanges;

Issue #18022Tracking issue #18022

Altes VerhaltenOld behavior

Vor Version 3.0 löste Eager Loading von Sammlungsnavigationen über Include-Operatoren die Generierung mehrerer Abfragen auf der relationalen Datenbank aus. Eine Abfrage für jeden verwandten Entitätstyp.Before 3.0, eagerly loading collection navigations via Include operators caused multiple queries to be generated on relational database, one for each related entity type.

Neues VerhaltenNew behavior

Ab Version 3.0 generiert EF Core eine einzelne Abfrage mit JOINs für relationale Datenbanken.Starting with 3.0, EF Core generates a single query with JOINs on relational databases.

HintergründeWhy

Das Ausgeben mehrerer Abfragen zum Implementieren einer einzelnen LINQ-Abfrage führte zu einer Vielzahl von Problemen, darunter Leistungsbeeinträchtigungen, da mehrere Datenbankroundtrips erforderlich waren, und Datenkohärenzprobleme, da jede Abfrage einen anderen Zustand der Datenbank beobachten könnte.Issuing multiple queries to implement a single LINQ query caused numerous issues, including negative performance as multiple database roundtrips were necessary, and data coherency issues as each query could observe a different state of the database.

Vorbeugende MaßnahmenMitigations

Zwar ist dies technisch gesehen kein Breaking Change, jedoch könnte es erhebliche Auswirkungen auf die Leistung der Anwendung haben, wenn eine einzelne Abfrage eine große Anzahl von Include-Operatoren für Sammlungsnavigationen enthält.While technically this is not a breaking change, it could have a considerable effect on application performance when a single query contains a large number of Include operator on collection navigations. Weitere Informationen sowie Informationen zum Umschreiben von Abfragen auf eine effizientere Weise finden Sie in diesem Kommentar.See this comment for more information and for rewriting queries in a more efficient way.

**

DeleteBehavior.Restrict verfügt über eine übersichtlichere SemantikDeleteBehavior.Restrict has cleaner semantics

Issue #12661Tracking Issue #12661

Altes VerhaltenOld behavior

Vor Version 3.0 wurden mit DeleteBehavior.Restrict Fremdschlüssel in der Datenbank mit Restrict-Semantik erstellt, es wurden aber auch unvorhergesehen interne Fixups geändert.Before 3.0, DeleteBehavior.Restrict created foreign keys in the database with Restrict semantics, but also changed internal fixup in a non-obvious way.

Neues VerhaltenNew behavior

Ab Version 3.0 wird mit DeleteBehavior.Restrict sichergestellt, dass Fremdschlüssel mit Restrict-Semantik erstellt werden – d. h. ohne Überlappungen; ausgenommen bei Einschränkungsverletzungen – und ohne Auswirkungen auf EF-interne Fixups.Starting with 3.0, DeleteBehavior.Restrict ensures that foreign keys are created with Restrict semantics--that is, no cascades; throw on constraint violation--without also impacting EF internal fixup.

HintergründeWhy

Diese Änderung wurde vorgenommen, um die Benutzerfreundlichkeit bei intuitiver Verwendung von DeleteBehavior ohne unerwartete Nebeneffekte zu verbessern.This change was made to improve the experience for using DeleteBehavior in an intuitive manner, without unexpected side-effects.

Vorbeugende MaßnahmenMitigations

Sie können das vorherige Verhalten wiederherstellen, indem Sie DeleteBehavior.ClientNoAction verwenden.The previous behavior can be restored by using DeleteBehavior.ClientNoAction.

Abfragetypen werden mit Entitätstypen zusammengeführtQuery types are consolidated with entity types

Issue #14194Tracking Issue #14194

Altes VerhaltenOld behavior

Vor Version 3.0 wurden in EF Core Abfragetypen dazu verwendet, Daten abzufragen, in denen kein Primärschlüssel auf strukturierte Weise festgelegt war.Before EF Core 3.0, query types were a means to query data that doesn't define a primary key in a structured way. Abfragetypen wurden also für die Zuordnung von Entitätstypen ohne Schlüssel verwendet (in der Regel in einer Sicht, in einigen Fällen aber auch in einer Tabelle), während reguläre Entitätstypen für einen verfügbaren Schlüssel verwendet wurden (in der Regel in einer Tabelle, in einigen Fällen aber auch in einer Sicht).That is, a query type was used for mapping entity types without keys (more likely from a view, but possibly from a table) while a regular entity type was used when a key was available (more likely from a table, but possibly from a view).

Neues VerhaltenNew behavior

Aus einem Abfragetyp wird nun einfach ein Entitätstyp ohne Primärschlüssel.A query type now becomes just an entity type without a primary key. Entitätstypen ohne Schlüssel besitzen die gleiche Funktionalität wie Abfragetypen in früheren Versionen.Keyless entity types have the same functionality as query types in previous versions.

HintergründeWhy

Diese Änderung wurde vorgenommen, um Unklarheiten bei der Verwendung von Abfragetypen zu beseitigen.This change was made to reduce the confusion around the purpose of query types. Abfragetypen sind schlüssellose Entitätstypen, die grundsätzlich schreibgeschützt sind. Sie sollten allerdings nicht allein wegen des Schreibschutzes verwendet werden.Specifically, they are keyless entity types and they are inherently read-only because of this, but they should not be used just because an entity type needs to be read-only. Des Weiteren werden sie oft Sichten zugeordnet, was aber nur daran liegt, dass für Letztere häufig keine Schlüssel definiert werden.Likewise, they are often mapped to views, but this is only because views often don't define keys.

Vorbeugende MaßnahmenMitigations

Die folgenden Teile der API sind durch die Änderungen veraltet:The following parts of the API are now obsolete:

  • ModelBuilder.Query<>() : Rufen Sie stattdessen ModelBuilder.Entity<>().HasNoKey() auf, um einen schlüssellosen Entitätstyp festzulegen.ModelBuilder.Query<>() - Instead ModelBuilder.Entity<>().HasNoKey() needs to be called to mark an entity type as having no keys. Dieses Verhalten wird nach wie vor nicht konventionsgemäß festgelegt, um Fehlkonfigurationen zu vermeiden, wenn ein Primärschlüssel erwartet wird, jedoch nicht mit der Konvention übereinstimmt.This would still not be configured by convention to avoid misconfiguration when a primary key is expected, but doesn't match the convention.
  • DbQuery<> : Verwenden Sie stattdessen DbSet<>.DbQuery<> - Instead DbSet<> should be used.
  • DbContext.Query<>() : Verwenden Sie stattdessen DbContext.Set<>().DbContext.Query<>() - Instead DbContext.Set<>() should be used.

Die Konfigurations-API für Beziehungen abhängiger (owned) Typen wurde geändertConfiguration API for owned type relationships has changed

Issue #12444 Issue #9148 Issue #14153Tracking Issue #12444 Tracking Issue #9148 Tracking Issue #14153

Altes VerhaltenOld behavior

Vor Version 3.0 wurde in EF Core die abhängige Beziehung direkt nach dem Aufruf von OwnsOne oder OwnsMany konfiguriert.Before EF Core 3.0, configuration of the owned relationship was performed directly after the OwnsOne or OwnsMany call.

Neues VerhaltenNew behavior

Ab Version 3.0 von EF Core ist eine Fluent-API verfügbar, mit der über WithOwner() eine Navigationseigenschaft für den Besitzer konfiguriert werden kann.Starting with EF Core 3.0, there is now fluent API to configure a navigation property to the owner using WithOwner(). Beispiel:For example:

modelBuilder.Entity<Order>.OwnsOne(e => e.Details).WithOwner(e => e.Order);

Die Konfiguration für die Beziehung zwischen Besitzertyp und abhängigem Typ sollte nun ähnlich wie bei der Konfiguration anderer Beziehungen nach WithOwner() verkettet werden.The configuration related to the relationship between owner and owned should now be chained after WithOwner() similarly to how other relationships are configured. Die Konfiguration für den abhängigen Typ wird jedoch weiterhin nach OwnsOne()/OwnsMany() verkettet.While the configuration for the owned type itself would still be chained after OwnsOne()/OwnsMany(). Beispiel:For example:

modelBuilder.Entity<Order>.OwnsOne(e => e.Details, eb =>
    {
        eb.WithOwner()
            .HasForeignKey(e => e.AlternateId)
            .HasConstraintName("FK_OrderDetails");
            
        eb.ToTable("OrderDetails");
        eb.HasKey(e => e.AlternateId);
        eb.HasIndex(e => e.Id);

        eb.HasOne(e => e.Customer).WithOne();

        eb.HasData(
            new OrderDetails
            {
                AlternateId = 1,
                Id = -1
            });
    });

Wenn Sie zusätzlich Entity(), HasOne(), oder Set() für das Ziel eines abhängigen Typs aufrufen, wird keine Ausnahme ausgelöst.Additionally calling Entity(), HasOne(), or Set() with an owned type target will now throw an exception.

HintergründeWhy

Diese Änderung wurde vorgenommen, um eine deutlichere Trennung zwischen der Konfiguration des abhängigen Typs und der Beziehung zum abhängigen Typ zu ermöglichen.This change was made to create a cleaner separation between configuring the owned type itself and the relationship to the owned type. Dadurch werden für Methoden wie HasForeignKey Mehrdeutigkeiten und Unklarheiten beseitigt.This in turn removes ambiguity and confusion around methods like HasForeignKey.

Vorbeugende MaßnahmenMitigations

Passen Sie für die Beziehungen von abhängigen Typen die Konfiguration so an, dass die neue Fluent-API wie im obigen Beispiel verwendet wird.Change configuration of owned type relationships to use the new API surface as shown in the example above.

Abhängige Entitäten, die die Tabelle gemeinsam mit dem Prinzipal verwenden, sind jetzt optionalDependent entities sharing the table with the principal are now optional

Issue #9005Tracking Issue #9005

Altes VerhaltenOld behavior

Sehen Sie sich das folgende Modell an:Consider the following model:

public class Order
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public OrderDetails Details { get; set; }
}

public class OrderDetails
{
    public int Id { get; set; }
    public string ShippingAddress { get; set; }
}

Wenn OrderDetails im Besitz von Order ist oder explizit derselben Tabelle zugeordnet ist, war vor Version 3.0 in EF Core immer eine OrderDetails-Instanz beim Hinzufügen eines neuen Order-Objekts erforderlich.Before EF Core 3.0, if OrderDetails is owned by Order or explicitly mapped to the same table then an OrderDetails instance was always required when adding a new Order.

Neues VerhaltenNew behavior

Ab Version 3.0 bietet EF Core die Möglichkeit, Order ohne OrderDetails hinzuzufügen, und alle OrderDetails-Eigenschaften, mit Ausnahme des primären Schlüssels, werden Spalten zugeordnet, die NULL-Werte zulassen.Starting with 3.0, EF Core allows to add an Order without an OrderDetails and maps all of the OrderDetails properties except the primary key to nullable columns. Bei Abfragen von EF Core wird OrderDetails auf null festgelegt, wenn eine der erforderlichen Eigenschaften keinen Wert aufweist oder keine erforderlichen Eigenschaften außer dem primären Schlüssel vorhanden und alle Eigenschaften null sind.When querying EF Core sets OrderDetails to null if any of its required properties doesn't have a value or if it has no required properties besides the primary key and all properties are null.

Vorbeugende MaßnahmenMitigations

Wenn Ihr Modell von der gemeinsamen Nutzung einer Tabelle mit allen optionalen Spalten abhängig ist, aber die Navigation, die darauf zeigt, wahrscheinlich nicht null ist, sollte die Anwendung für die Handhabung von Fällen geändert werden, in denen die Navigation null ist.If your model has a table sharing dependent with all optional columns, but the navigation pointing to it is not expected to be null then the application should be modified to handle cases when the navigation is null. Wenn das nicht möglich ist, sollte dem Entitätstyp eine erforderliche Eigenschaft hinzugefügt werden oder mindestens einer Eigenschaft sollte ein Wert ungleich null zugewiesen sein.If this is not possible a required property should be added to the entity type or at least one property should have a non-null value assigned to it.

Alle Entitäten, die eine Tabelle mit einer Spalte für das Parallelitätstoken gemeinsam verwenden, müssen diese einer Eigenschaft zuordnenAll entities sharing a table with a concurrency token column have to map it to a property

Issue #14154Tracking Issue #14154

Altes VerhaltenOld behavior

Sehen Sie sich das folgende Modell an:Consider the following model:

public class Order
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public byte[] Version { get; set; }
    public OrderDetails Details { get; set; }
}

public class OrderDetails
{
    public int Id { get; set; }
    public string ShippingAddress { get; set; }
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Order>()
        .Property(o => o.Version).IsRowVersion().HasColumnName("Version");
}

Wenn OrderDetails im Besitz von Order ist oder explizit derselben Tabelle zugeordnet ist, wird vor Version 3.0 in EF Core durch das alleinige Aktualisieren von OrderDetails der Version-Wert auf dem Client nicht aktualisiert, und das nächste Update schlägt fehl.Before EF Core 3.0, if OrderDetails is owned by Order or explicitly mapped to the same table then updating just OrderDetails will not update Version value on client and the next update will fail.

Neues VerhaltenNew behavior

Ab Version 3.0 gibt EF Core den neuen Version-Wert an Order weiter, wenn dies Besitzer von OrderDetails ist.Starting with 3.0, EF Core propagates the new Version value to Order if it owns OrderDetails. Andernfalls wird eine Ausnahme während der Modellvalidierung ausgelöst.Otherwise an exception is thrown during model validation.

HintergründeWhy

Diese Änderung wurde vorgenommen, um einen veralteten Wert für ein Parallelitätstoken zu vermeiden, wenn nur eine der Entitäten, die derselben Tabelle zugeordnet sind, aktualisiert wird.This change was made to avoid a stale concurrency token value when only one of the entities mapped to the same table is updated.

Vorbeugende MaßnahmenMitigations

Alle Entitäten, die die Tabelle gemeinsam nutzen, müssen eine Eigenschaft enthalten, die der Spalte für das Parallelitätstoken zugeordnet ist.All entities sharing the table have to include a property that is mapped to the concurrency token column. Es ist möglich, eine solche im Schattenzustand zu erstellen:It's possible the create one in shadow-state:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<OrderDetails>()
        .Property<byte[]>("Version").IsRowVersion().HasColumnName("Version");
}

Geerbte Eigenschaften von nicht zugeordneten Typen sind nun einer einzelnen Spalte für alle abgeleiteten Typen zugeordnetInherited properties from unmapped types are now mapped to a single column for all derived types

Issue #13998Tracking Issue #13998

Altes VerhaltenOld behavior

Sehen Sie sich das folgende Modell an:Consider the following model:

public abstract class EntityBase
{
    public int Id { get; set; }
}

public abstract class OrderBase : EntityBase
{
    public int ShippingAddress { get; set; }
}

public class BulkOrder : OrderBase
{
}

public class Order : OrderBase
{
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Ignore<OrderBase>();
    modelBuilder.Entity<EntityBase>();
    modelBuilder.Entity<BulkOrder>();
    modelBuilder.Entity<Order>();
}

Vor Version 3.0 wurde in EF Core die Eigenschaft ShippingAddress standardmäßig separaten Spalten für BulkOrder und Order zugeordnet.Before EF Core 3.0, the ShippingAddress property would be mapped to separate columns for BulkOrder and Order by default.

Neues VerhaltenNew behavior

Ab Version 3.0 erstellt EF Core nur eine Spalte für ShippingAddress.Starting with 3.0, EF Core only creates one column for ShippingAddress.

HintergründeWhy

Der alte Verhalten war unerwartet.The old behavoir was unexpected.

Vorbeugende MaßnahmenMitigations

Die Eigenschaft kann noch immer explizit einer separaten Spalte für die abgeleiteten Typen zugeordnet werden:The property can still be explicitly mapped to separate column on the derived types:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Ignore<OrderBase>();
    modelBuilder.Entity<EntityBase>();
    modelBuilder.Entity<BulkOrder>()
        .Property(o => o.ShippingAddress).HasColumnName("BulkShippingAddress");
    modelBuilder.Entity<Order>()
        .Property(o => o.ShippingAddress).HasColumnName("ShippingAddress");
}

Die Konvention zur Fremdschlüsseleigenschaft entspricht nicht mehr dem Namen der PrinzipaleigenschaftThe foreign key property convention no longer matches same name as the principal property

Issue #13274Tracking Issue #13274

Altes VerhaltenOld behavior

Sehen Sie sich das folgende Modell an:Consider the following model:

public class Customer
{
    public int CustomerId { get; set; }
    public ICollection<Order> Orders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
}

Vor Version 3.0 wurde in EF Core gemäß der Konvention die CustomerId-Eigenschaft für den Fremdschlüssel verwendet.Before EF Core 3.0, the CustomerId property would be used for the foreign key by convention. Wenn Order jedoch ein abhängiger Typ ist, wäre CustomerId der Primärschlüssel, was normalerweise nicht der Erwartungshaltung entspricht.However, if Order is an owned type, then this would also make CustomerId the primary key and this isn't usually the expectation.

Neues VerhaltenNew behavior

Ab Version 3.0 werden in EF Core konventionsgemäß keine Eigenschaften mehr für Fremdschlüssel verwendet, wenn diese denselben Namen wie die Prinzipaleigenschaft besitzen.Starting with 3.0, EF Core doesn't try to use properties for foreign keys by convention if they have the same name as the principal property. Die Muster für den Namen des Prinzipaltyps, der mit dem Namen der Prinzipaleigenschaft verkettet wird, und für den Navigationsnamen, der mit dem Namen der Prinzipaleigenschaft verkettet wird, werden jedoch weiterhin abgeglichen.Principal type name concatenated with principal property name, and navigation name concatenated with principal property name patterns are still matched. Beispiel:For example:

public class Customer
{
    public int Id { get; set; }
    public ICollection<Order> Orders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
}
public class Customer
{
    public int Id { get; set; }
    public ICollection<Order> Orders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public int BuyerId { get; set; }
    public Customer Buyer { get; set; }
}

HintergründeWhy

Diese Änderung wurde vorgenommen, um zu vermeiden, dass versehentlich eine Primärschlüsseleigenschaft für den abhängigen Typ definiert wird.This change was made to avoid erroneously defining a primary key property on the owned type.

Vorbeugende MaßnahmenMitigations

Wenn die Eigenschaft als Fremdschlüssel und daher Teil des Primärschlüssels vorgesehen war, müssen Sie diese explizit als solche festlegen.If the property was intended to be the foreign key, and hence part of the primary key, then explicitly configure it as such.

Die Datenbankverbindung wird jetzt geschlossen, wenn sie nicht mehr verwendet wird, bevor TransactionScope abgeschlossen wurdeDatabase connection is now closed if not used anymore before the TransactionScope has been completed

Issue #14218Tracking Issue #14218

Altes VerhaltenOld behavior

Wenn vor Version 3.0 in EF Core der Kontext die Verbindung in einem TransactionScope öffnet, bleibt die Verbindung geöffnet, während der aktuelle TransactionScope aktiv ist.Before EF Core 3.0, if the context opens the connection inside a TransactionScope, the connection remains open while the current TransactionScope is active.

using (new TransactionScope())
{
    using (AdventureWorks context = new AdventureWorks())
    {
        context.ProductCategories.Add(new ProductCategory());
        context.SaveChanges();

        // Old behavior: Connection is still open at this point
        
        var categories = context.ProductCategories().ToList();
    }
}

Neues VerhaltenNew behavior

Ab Version 3.0 schließt EF Core die Verbindung, sobald sie nicht mehr verwendet wird.Starting with 3.0, EF Core closes the connection as soon as it's done using it.

HintergründeWhy

Diese Änderung ermöglicht die Verwendung mehrerer Kontexte in demselben TransactionScope.This change allows to use multiple contexts in the same TransactionScope. Das neue Verhalten entspricht außerdem EF6.The new behavior also matches EF6.

Vorbeugende MaßnahmenMitigations

Wenn die Verbindung geöffnet bleiben muss, wird durch einen expliziten Aufruf von OpenConnection() sichergestellt, dass EF Core diese nicht vorzeitig schließt:If the connection needs to remain open explicit call to OpenConnection() will ensure that EF Core doesn't close it prematurely:

using (new TransactionScope())
{
    using (AdventureWorks context = new AdventureWorks())
    {
        context.Database.OpenConnection();
        context.ProductCategories.Add(new ProductCategory());
        context.SaveChanges();
        
        var categories = context.ProductCategories().ToList();
        context.Database.CloseConnection();
    }
}

Für jede Eigenschaft wird separat ein ganzzahliger speicherinterner Schlüssel generiertEach property uses independent in-memory integer key generation

Issue #6872Tracking Issue #6872

Altes VerhaltenOld behavior

Vor Version 3.0 wurde in EF Core ein gemeinsam verwendeter Wertegenerator für alle speicherinternen ganzzahligen Schlüsseleigenschaften verwendet.Before EF Core 3.0, one shared value generator was used for all in-memory integer key properties.

Neues VerhaltenNew behavior

Ab Version 3.0 von EF Core wird für jede ganzzahlige Schlüsseleigenschaft ein eigener Wertegenerator bei der Verwendung der In-Memory Database verwendet.Starting with EF Core 3.0, each integer key property gets its own value generator when using the in-memory database. Wenn die Datenbank gelöscht wird, wird die Schlüsselgenerierung für alle Tabellen zurückgesetzt.Also, if the database is deleted, then key generation is reset for all tables.

HintergründeWhy

Diese Änderung wurde vorgenommen, um die speicherinterne Schlüsselgenerierung enger mit der Schlüsselgenerierung für echte Datenbanken abzustimmen. Außerdem sollen bei Verwendung der In-Memory Database Tests leichter voneinander isoliert werden können.This change was made to align in-memory key generation more closely to real database key generation and to improve the ability to isolate tests from each other when using the in-memory database.

Vorbeugende MaßnahmenMitigations

Wenn Anwendungen von bestimmten speicherinternen Schlüsselwerten abhängig sind, funktionieren Erstere durch die eingeführte Änderung möglicherweise nicht mehr.This can break an application that is relying on specific in-memory key values to be set. Versuchen Sie, Abhängigkeiten von bestimmten Schlüsselwerten zu vermeiden, oder passen Sie die Anwendung an das neue Verhalten an.Consider instead not relying on specific key values, or updating to match the new behavior.

Unterstützungsfelder werden standardmäßig verwendetBacking fields are used by default

Issue #12430Tracking Issue #12430

Altes VerhaltenOld behavior

Vor Version 3.0 wurde in EF Core mithilfe der Getter- und Settermethoden standardmäßig der Eigenschaftswert gelesen und geschrieben. Das war selbst dann der Fall, wenn das Unterstützungsfeld für eine Eigenschaft nicht bekannt war.Before 3.0, even if the backing field for a property was known, EF Core would still by default read and write the property value using the property getter and setter methods. Eine Ausnahme war die Abfrageausführung, bei der das Unterstützungsfeld direkt festgelegt wurde, wenn es bekannt war.The exception to this was query execution, where the backing field would be set directly if known.

Neues VerhaltenNew behavior

Ab Version 3.0 wird in EF Core die Eigenschaft mithilfe des Unterstützungsfelds gelesen und geschrieben, wenn dieses für eine Eigenschaft bekannt ist.Starting with EF Core 3.0, if the backing field for a property is known, then EF Core will always read and write that property using the backing field. Dies kann dazu führen, dass eine Anwendung nicht mehr funktioniert, wenn sie auf zusätzliches Verhalten angewiesen ist, das im Code der Getter- und Settermethoden definiert ist.This could cause an application break if the application is relying on additional behavior coded into the getter or setter methods.

HintergründeWhy

Diese Änderung wurde vorgenommen, um zu verhindern, dass in EF Core fälschlicherweise immer dann Geschäftslogik ausgelöst wird, wenn Datenbankvorgänge für Entitäten durchgeführt werden.This change was made to prevent EF Core from erroneously triggering business logic by default when performing database operations involving the entities.

Vorbeugende MaßnahmenMitigations

Sie können das Verhalten von vor Version 3.0 wiederherstellen, indem Sie in ModelBuilder den Zugriffsmodus für die Eigenschaft konfigurieren.The pre-3.0 behavior can be restored through configuration of the property access mode on ModelBuilder. Beispiel:For example:

modelBuilder.UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction);

Eine Ausnahme wird ausgelöst, wenn mehrere kompatible Unterstützungsfelder gefunden werdenThrow if multiple compatible backing fields are found

Issue #12523Tracking Issue #12523

Altes VerhaltenOld behavior

Vor Version 3.0 wurde in EF Core ein Unterstützungsfeld auf Grundlage einer Rangfolge ausgewählt, wenn die Regeln zum Suchen eines Eigenschaftsfelds auf mehrere Felder zutrafen.Before EF Core 3.0, if multiple fields matched the rules for finding the backing field of a property, then one field would be chosen based on some precedence order. Dabei konnte es vorkommen, dass in mehrdeutigen Fällen das falsche Feld verwendet wurde.This could cause the wrong field to be used in ambiguous cases.

Neues VerhaltenNew behavior

Ab Version 3.0 wird in EF Core eine Ausnahme ausgelöst, wenn sich mehrere Felder auf dieselbe Eigenschaft beziehen.Starting with EF Core 3.0, if multiple fields are matched to the same property, then an exception is thrown.

HintergründeWhy

Diese Änderung wurde vorgenommen, um zu vermeiden, dass automatisch ein falsches Feld verwendet wird.This change was made to avoid silently using one field over another when only one can be correct.

Vorbeugende MaßnahmenMitigations

Für Eigenschaften mit mehrdeutigen Unterstützungsfeldern muss das zu verwendende Feld explizit festgelegt werden.Properties with ambiguous backing fields must have the field to use specified explicitly. Mit der Fluent-API ist dies beispielsweise wie folgt möglich:For example, using the fluent API:

modelBuilder
    .Entity<Blog>()
    .Property(e => e.Id)
    .HasField("_id");

„Nur-Feld“-Eigenschaftsnamen sollten dem Feldnamen entsprechenField-only property names should match the field name

Altes VerhaltenOld behavior

Vor Version 3.0 konnte in EF Core eine Eigenschaft durch einen Zeichenfolgenwert angegeben werden, und wenn keine Eigenschaft mit diesem Namen im .NET-Typ gefunden wurde, versuchte EF Core, mithilfe von Konventionsregeln ein übereinstimmendes Feld zu finden.Before EF Core 3.0, a property could be specified by a string value and if no property with that name was found on the .NET type then EF Core would try to match it to a field using convention rules.

private class Blog
{
    private int _id;
    public string Name { get; set; }
}
modelBuilder
    .Entity<Blog>()
    .Property("Id");

Neues VerhaltenNew behavior

Ab Version 3.0 muss in EF Core eine „Nur-Feld“-Eigenschaft mit dem Namen des Felds genau übereinstimmen.Starting with EF Core 3.0, a field-only property must match the field name exactly.

modelBuilder
    .Entity<Blog>()
    .Property("_id");

HintergründeWhy

Diese Änderung wurde vorgenommen, um zu vermeiden, dass das gleiche Feld für zwei Eigenschaften mit ähnlichem Namen verwendet wird. Durch die Änderung entsprechen nun auch die Übereinstimmungsregeln für „Nur-Feld“-Eigenschaften den Regeln für Eigenschaften, die CLR-Eigenschaften zugeordnet sind.This change was made to avoid using the same field for two properties named similarly, it also makes the matching rules for field-only properties the same as for properties mapped to CLR properties.

Vorbeugende MaßnahmenMitigations

„Nur-Feld“-Eigenschaften müssen so benannt werden wie das Feld, dem sie zugeordnet sind.Field-only properties must be named the same as the field they are mapped to. In einer kommenden Version von EF Core nach 3.0 soll das explizite Konfigurieren eines Feldnamens, der sich vom Eigenschaftsnamen unterscheidet, erneut aktiviert werden (siehe Problem #15307):In a future release of EF Core after 3.0, we plan to re-enable explicitly configuring a field name that is different from the property name (see issue #15307):

modelBuilder
    .Entity<Blog>()
    .Property("Id")
    .HasField("_id");

Von AddDbContext/AddDbContextPool werden AddLogging und AddMemoryCache nicht mehr aufgerufen.AddDbContext/AddDbContextPool no longer call AddLogging and AddMemoryCache

Issue #14756Tracking Issue #14756

Altes VerhaltenOld behavior

Vor EF Core 3.0 wurden beim Aufruf von AddDbContext oder AddDbContextPool durch Aufrufe von AddLogging und AddMemoryCache auch Protokollierungs- und Arbeitsspeichercaching-Dienste bei DI registriert.Before EF Core 3.0, calling AddDbContext or AddDbContextPool would also register logging and memory caching services with D.I through calls to AddLogging and AddMemoryCache.

Neues VerhaltenNew behavior

Ab EF Core 3.0 werden diese Dienste durch AddDbContext und AddDbContextPool nicht mehr bei Dependency Injection (DI) registriert.Starting with EF Core 3.0, AddDbContext and AddDbContextPool will no longer register these services with Dependency Injection (DI).

HintergründeWhy

Für EF Core 3.0 ist es nicht erforderlich, dass diese Dienste im DI-Container der Anwendung enthalten sind.EF Core 3.0 does not require that these services are in the application's DI container. Wenn ILoggerFactory jedoch im DI-Container der Anwendung registriert ist, wird sie nach wie vor von EF Core verwendet.However, if ILoggerFactory is registered in the application's DI container, then it will still be used by EF Core.

Vorbeugende MaßnahmenMitigations

Wenn Ihre Anwendung diese Dienste benötigt, registrieren Sie sie explizit mit AddLogging oder AddMemoryCache beim DI-Container.If your application needs these services, then register them explicitly with the DI container using AddLogging or AddMemoryCache.

DbContext.Entry erkennt nun mit DetectChanges lokale ÄnderungenDbContext.Entry now performs a local DetectChanges

Issue #13552Tracking Issue #13552

Altes VerhaltenOld behavior

Vor Version 3.0 führte in EF Core ein Aufruf von DbContext.Entry dazu, dass Änderungen an allen überwachten Entitäten erkannt wurden.Before EF Core 3.0, calling DbContext.Entry would cause changes to be detected for all tracked entities. Dadurch wurde sichergestellt, dass der Zustand in EntityEntry immer aktuell war.This ensured that the state exposed in the EntityEntry was up-to-date.

Neues VerhaltenNew behavior

Ab Version 3.0 werden in EF Core Änderungen bei einem Aufruf von DbContext.Entry nur in der angegebenen Entität und in allen überwachten Prinzipalentitäten erkannt.Starting with EF Core 3.0, calling DbContext.Entry will now only attempt to detect changes in the given entity and any tracked principal entities related to it. Änderungen an anderer Stelle werden daher durch den Aufruf dieser Methode möglicherweise nicht erkannt, was sich auf den Anwendungszustand auswirken kann.This means that changes elsewhere may not have been detected by calling this method, which could have implications on application state.

Beachten Sie, dass selbst die Erkennung lokaler Änderungen deaktiviert wird, wenn ChangeTracker.AutoDetectChangesEnabled auf false festgelegt wird.Note that if ChangeTracker.AutoDetectChangesEnabled is set to false then even this local change detection will be disabled.

Andere Methoden wie ChangeTracker.Entries und SaveChanges, die eine Änderungserkennung auslösen, führen nach wie vor zu einem vollständigen DetectChanges-Vorgang für alle überwachten Entitäten.Other methods that cause change detection--for example ChangeTracker.Entries and SaveChanges--still cause a full DetectChanges of all tracked entities.

HintergründeWhy

Diese Änderung wurde vorgenommen, um die Leistung bei der standardmäßigen Verwendung von context.Entry zu verbessern.This change was made to improve the default performance of using context.Entry.

Vorbeugende MaßnahmenMitigations

Rufen Sie ChgangeTracker.DetectChanges() explizit vor dem Aufruf von Entry auf, wenn das Verhalten vor Version 3.0 beibehalten werden soll.Call ChgangeTracker.DetectChanges() explicitly before calling Entry to ensure the pre-3.0 behavior.

Schlüssel aus Zeichenfolgen und Bytearrays werden standardmäßig nicht vom Client generiertString and byte array keys are not client-generated by default

Issue #14617Tracking Issue #14617

Altes VerhaltenOld behavior

Vor Version 3.0 konnten in EF Core string- und byte[]-Schlüsseleigenschaften verwendet werden, ohne dass explizit ein anderer Wert als NULL festgelegt werden musste.Before EF Core 3.0, string and byte[] key properties could be used without explicitly setting a non-null value. In diesem Fall wurde der Schlüsselwert auf dem Client als GUID generiert und für byte[] in Bytes serialisiert.In such a case, the key value would be generated on the client as a GUID, serialized to bytes for byte[].

Neues VerhaltenNew behavior

Ab Version 3.0 wird in EF Core eine Ausnahme ausgelöst, wenn kein Schlüsselwert festgelegt wird.Starting with EF Core 3.0 an exception will be thrown indicating that no key value has been set.

HintergründeWhy

Diese Änderung wurde vorgenommen, da vom Client generierte string/byte[]-Werte in der Regel nicht sinnvoll sind. Das Standardverhalten führte außerdem zu kaum nachvollziehbaren generierten Schlüsselwerten.This change was made because client-generated string/byte[] values generally aren't useful, and the default behavior made it hard to reason about generated key values in a common way.

Vorbeugende MaßnahmenMitigations

Wenn Sie das Verhalten vor Version 3.0 nutzen möchten, müssen Sie explizit festlegen, dass für die Schlüsseleigenschaften generierte Werte verwendet sollen, wenn kein anderer Nicht-NULL-Wert festgelegt wird.The pre-3.0 behavior can be obtained by explicitly specifying that the key properties should use generated values if no other non-null value is set. Dies ist beispielsweise mit der Fluent-API möglich:For example, with the fluent API:

modelBuilder
    .Entity<Blog>()
    .Property(e => e.Id)
    .ValueGeneratedOnAdd();

Alternativ bieten sich auch Datenanmerkungen an:Or with data annotations:

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; set; }

ILoggerFactory ist nun ein bereichsbezogener DienstILoggerFactory is now a scoped service

Issue #14698Tracking Issue #14698

Altes VerhaltenOld behavior

Vor Version 3.0 wurde ILoggerFactory in EF Core als Singletondienst registriert.Before EF Core 3.0, ILoggerFactory was registered as a singleton service.

Neues VerhaltenNew behavior

Ab Version 3.0 wird in EF Core ILoggerFactory als bereichsbezogener Dienst registriert.Starting with EF Core 3.0, ILoggerFactory is now registered as scoped.

HintergründeWhy

Diese Änderung wurde vorgenommen, um einer DbContext-Instanz eine Protokollierung zuordnen zu können. Dadurch werden weitere Funktionen bereitgestellt. In einigen Fällen wird außerdem schädliches Verhalten wie etwa die schnelle Zunahme von internen Dienstanbietern beseitigt.This change was made to allow association of a logger with a DbContext instance, which enables other functionality and removes some cases of pathological behavior such as an explosion of internal service providers.

Vorbeugende MaßnahmenMitigations

Diese Änderung wirkt sich nur dann auf den Anwendungscode aus, wenn benutzerdefinierte Dienste auf dem internen Dienstanbieter von EF Core registriert und verwendet werden.This change should not impact application code unless it is registering and using custom services on the EF Core internal service provider. Ein solches Szenario ist aber unüblich.This isn't common. In einem derartigen Fall funktioniert fast alles wie vorher. Singletondienste, die von ILoggerFactory abhängig sind, müssen jedoch so angepasst werden, dass ILoggerFactory auf andere Weise abgerufen wird.In these cases, most things will still work, but any singleton service that was depending on ILoggerFactory will need to be changed to obtain the ILoggerFactory in a different way.

Erstellen Sie in diesen Situationen bitte im GitHub-Issuetracker für EF Core ein Issue, in dem Sie beschreiben, wie Sie ILoggerFactory verwenden. So können wir in Zukunft erneute Breaking Changes vermeiden.If you run into situations like this, please file an issue at on the EF Core GitHub issue tracker to let us know how you are using ILoggerFactory such that we can better understand how not to break this again in the future.

Für Proxys mit Lazy Loading (trägem Laden) gilt nicht mehr die Annahme, dass Navigationseigenschaften vollständig geladen sindLazy-loading proxies no longer assume navigation properties are fully loaded

Issue #12780Tracking Issue #12780

Altes VerhaltenOld behavior

Vor Version 3.0 gab es in EF Core nach der Freigabe eines DbContext-Objekts keine Möglichkeit, zu ermitteln, ob eine aus dem Kontext abgerufene Navigationseigenschaft für eine Entität vollständig geladen war.Before EF Core 3.0, once a DbContext was disposed there was no way of knowing if a given navigation property on an entity obtained from that context was fully loaded or not. Stattdessen galt für Proxys die Annahme, dass eine Verweisnavigation geladen ist, falls für diese ein anderer Wert als NULL vorliegt. Außerdem wurde davon ausgegangen, dass eine Sammlungsnavigation geladen ist, wenn sie nicht leer ist.Proxies would instead assume that a reference navigation is loaded if it has a non-null value, and that a collection navigation is loaded if it isn't empty. In diesen Fällen entsprach das Lazy Loading einer Nulloperation („No-Op“).In these cases, attempting to lazy-load would be a no-op.

Neues VerhaltenNew behavior

Ab Version 3.0 überwachen in EF Core Proxys, ob eine Navigationseigenschaft geladen ist.Starting with EF Core 3.0, proxies keep track of whether or not a navigation property is loaded. Wenn also auf eine Navigationseigenschaft zugegriffen werden soll, die nach der Freigabe des Kontexts geladen wird, ist dies immer eine No-Op-Operation. Das ist selbst dann der Fall, wenn die geladene Navigation leer oder NULL ist.This means attempting to access a navigation property that is loaded after the context has been disposed will always be a no-op, even when the loaded navigation is empty or null. Wenn umgekehrt auf eine nicht geladene Navigationseigenschaft zugegriffen werden soll und der Kontext bereits freigegeben wurde, wird eine Ausnahme ausgelöst. Dieser Fall tritt auch dann ein, wenn die Navigationseigenschaft eine nicht leere Sammlung ist.Conversely, attempting to access a navigation property that isn't loaded will throw an exception if the context is disposed even if the navigation property is a non-empty collection. In dieser Situation wird also vom Anwendungscode versucht, zu einem ungültigen Zeitpunkt Lazy Loading durchzuführen. Die Anwendung sollte so angepasst werden, dass dieser Vorgang vermieden wird.If this situation arises, it means the application code is attempting to use lazy-loading at an invalid time, and the application should be changed to not do this.

HintergründeWhy

Diese Änderung wurde vorgenommen, um das Verhalten beim Lazy Loading einer freigegebenen DbContext-Instanz konsistent und korrekt zu gestalten.This change was made to make the behavior consistent and correct when attempting to lazy-load on a disposed DbContext instance.

Vorbeugende MaßnahmenMitigations

Aktualisieren Sie den Anwendungscode so, dass kein Lazy Loading durchgeführt wird, nachdem der Kontext freigegeben wurde. Alternativ können Sie auch, wie in der Ausnahmemeldung beschrieben wird, eine No-Op-Operation festlegen.Update application code to not attempt lazy-loading with a disposed context, or configure this to be a no-op as described in the exception message.

Die Erstellung zu vieler interner Dienstanbieter führt standardmäßig zu einem FehlerExcessive creation of internal service providers is now an error by default

Issue #10236Tracking Issue #10236

Altes VerhaltenOld behavior

Vor Version 3.0 wurde in EF Core eine Warnung für eine Anwendung protokolliert, die unverhältnismäßig viele interne Dienstanbieter erstellte.Before EF Core 3.0, a warning would be logged for an application creating a pathological number of internal service providers.

Neues VerhaltenNew behavior

Ab Version 3.0 wird diese Warnung in EF Core als Fehler betrachtet, und eine Ausnahme wird ausgelöst.Starting with EF Core 3.0, this warning is now considered and error and an exception is thrown.

HintergründeWhy

Diese Änderung wurde vorgenommen, damit auf den oben beschriebenen Fall explizit hingewiesen wird. So soll die Entwicklung von besserem Anwendungscode erleichtert werden.This change was made to drive better application code through exposing this pathological case more explicitly.

Vorbeugende MaßnahmenMitigations

Wenn dieser Fehler auftritt, müssen Sie die Grundursache ermitteln und die Erstellung vieler interner Dienstanbieter unterbinden.The most appropriate cause of action on encountering this error is to understand the root cause and stop creating so many internal service providers. Sie können den Fehler allerdings auch wieder in eine Warnung konvertierten (oder ihn ignorieren), indem Sie DbContextOptionsBuilder konfigurieren.However, the error can be converted back to a warning (or ignored) via configuration on the DbContextOptionsBuilder. Beispiel:For example:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .ConfigureWarnings(w => w.Log(CoreEventId.ManyServiceProvidersCreatedWarning));
}

Neues Verhalten für HasOne/HasMany bei Aufruf mit einer einzelnen ZeichenfolgeNew behavior for HasOne/HasMany called with a single string

Issue #9171Tracking Issue #9171

Altes VerhaltenOld behavior

Vor EF Core 3.0 wurde Code, der HasOne oder HasMany mit einer einzelnen Zeichenfolge aufruft, auf irritierende Weise interpretiert.Before EF Core 3.0, code calling HasOne or HasMany with a single string was interpreted in a confusing way. Beispiel:For example:

modelBuilder.Entity<Samurai>().HasOne("Entrance").WithOne();

Der Code scheint Samurai mit einem anderen Entitätstyp über die Entrance-Navigationseigenschaft zu verknüpfen, die möglicherweise privat ist.The code looks like it is relating Samurai to some other entity type using the Entrance navigation property, which may be private.

Tatsächlich versucht dieser Code, eine Beziehung zu einem Entitätstyp namens Entrance ohne Navigationseigenschaft herzustellen.In reality, this code attempts to create a relationship to some entity type called Entrance with no navigation property.

Neues VerhaltenNew behavior

Ab EF Core 3.0 führt der obige Code jetzt die erwartete Aktion durch.Starting with EF Core 3.0, the code above now does what it looked like it should have been doing before.

HintergründeWhy

Das alte Verhalten war sehr verwirrend, vor allem beim Lesen des Konfigurationscodes und bei der Suche nach Fehlern.The old behavior was very confusing, especially when reading the configuration code and looking for errors.

Vorbeugende MaßnahmenMitigations

Dies führt nur zu Fehlern in Anwendungen, die Beziehungen explizit unter Verwendung von Zeichenfolgen für Typnamen und ohne explizite Angabe der Navigationseigenschaft konfigurieren.This will only break applications that are explicitly configuring relationships using strings for type names and without specifying the navigation property explicitly. Dies ist nicht üblich.This is not common. Das vorherige Verhalten kann durch explizite Übergabe von null für den Namen der Navigationseigenschaft erzielt werden.The previous behavior can be obtained through explicitly passing null for the navigation property name. Beispiel:For example:

modelBuilder.Entity<Samurai>().HasOne("Some.Entity.Type.Name", null).WithOne();

Der Rückgabetyp für mehrere asynchrone Methoden wurde von Task in ValueTask geändertThe return type for several async methods has been changed from Task to ValueTask

Issue #15184Tracking Issue #15184

Altes VerhaltenOld behavior

Die folgenden asynchronen Methoden gaben zuvor Task<T> zurück:The following async methods previously returned a Task<T>:

  • DbContext.FindAsync()
  • DbSet.FindAsync()
  • DbContext.AddAsync()
  • DbSet.AddAsync()
  • ValueGenerator.NextValueAsync() (und abgeleitete Klassen)ValueGenerator.NextValueAsync() (and deriving classes)

Neues VerhaltenNew behavior

Die oben genannten Methoden geben nun ValueTask<T> über dieselbe T wie zuvor zurück.The aforementioned methods now return a ValueTask<T> over the same T as before.

HintergründeWhy

Durch diese Änderung verringert sich die Anzahl der Heapzuordnungen, die beim Aufrufen dieser Methoden entstehen, und dies führt zu einer Verbesserung der allgemeinen Leistung.This change reduces the number of heap allocations incurred when invoking these methods, improving general performance.

Vorbeugende MaßnahmenMitigations

Anwendungen, die einfach die oben genannten APIs erwarten, müssen nur neu kompiliert werden – Quelländerungen sind nicht erforderlich.Applications simply awaiting the above APIs only need to be recompiled - no source changes are necessary. Eine komplexere Verwendung (z.B. Übergeben der zurückgegebenen Task an Task.WhenAny()) erfordern in der Regel, dass die zurückgegebene ValueTask<T> durch einen Aufruf von AsTask() in Task<T> konvertiert wird.A more complex usage (e.g. passing the returned Task to Task.WhenAny()) typically require that the returned ValueTask<T> be converted to a Task<T> by calling AsTask() on it. Beachten Sie, dass dadurch die mit dieser Änderung verbundene Verringerung der Zuordnungen aufgehoben wird.Note that this negates the allocation reduction that this change brings.

Die Anmerkung Relational:TypeMapping heißt nun nur noch TypeMappingThe Relational:TypeMapping annotation is now just TypeMapping

Issue #9913Tracking Issue #9913

Altes VerhaltenOld behavior

Der Anmerkungsname für Typzuordnungsanmerkungen war bisher Relational:TypeMapping.The annotation name for type mapping annotations was "Relational:TypeMapping".

Neues VerhaltenNew behavior

Der Anmerkungsname für Typzuordnungsanmerkungen lautet nun TypeMapping.The annotation name for type mapping annotations is now "TypeMapping".

HintergründeWhy

Typzuordnungen werden nicht mehr ausschließlich für Anbieter relationaler Datenbanken verwendet.Type mappings are now used for more than just relational database providers.

Vorbeugende MaßnahmenMitigations

Diese Änderung ist nur dann ein Breaking Change, wenn Anwendungen direkt über eine Anmerkung auf die Typzuordnung zugreifen. Dieses Szenario ist jedoch unüblich.This will only break applications that access the type mapping directly as an annotation, which isn't common. Verzichten Sie daher darauf, die Anmerkung direkt zu verwenden, und greifen Sie stattdessen über die Fluent-API auf Typzuordnungen zu, um das Problem zu beheben.The most appropriate action to fix is to use API surface to access type mappings rather than using the annotation directly.

ToTable löst für einen abgeleiteten Typ eine Ausnahme ausToTable on a derived type throws an exception

Issue #11811Tracking Issue #11811

Altes VerhaltenOld behavior

Vor Version 3.0 wurde in EF Core der Aufruf von ToTable() für einen abgeleiteten Typ ignoriert, da TPH die einzige Strategie zur Vererbungszuordnung war und diese in unzulässigen Fällen angewendet wurde.Before EF Core 3.0, ToTable() called on a derived type would be ignored since only inheritance mapping strategy was TPH where this isn't valid.

Neues VerhaltenNew behavior

Ab Version 3.0 wird in EF Core eine Ausnahme ausgelöst, um später eine unerwartete Zuordnung zu vermeiden, wenn ToTable() für einen abgeleiteten Typ aufgerufen wird. Dieser Schritt dient auch als Vorbereitung für die TPT- und TPC-Unterstützung, die in einem künftigen Release folgen wird.Starting with EF Core 3.0 and in preparation for adding TPT and TPC support in a later release, ToTable() called on a derived type will now throw an exception to avoid an unexpected mapping change in the future.

HintergründeWhy

Derzeit ist es nicht zulässig, einen abgeleiteten Typ einer anderen Tabelle zuzuordnen.Currently it isn't valid to map a derived type to a different table. Durch diese Änderung werden Breaking Changes vermieden, wenn der beschriebene Vorgang in Zukunft zulässig wird.This change avoids breaking in the future when it becomes a valid thing to do.

Vorbeugende MaßnahmenMitigations

Entfernen Sie alle Zuordnungen von abgeleiteten Typen zu anderen Tabellen.Remove any attempts to map derived types to other tables.

ForSqlServerHasIndex wurde durch HasIndex ersetztForSqlServerHasIndex replaced with HasIndex

Issue #12366Tracking Issue #12366

Altes VerhaltenOld behavior

Vor Version 3.0 konnten in EF Core mit ForSqlServerHasIndex().ForSqlServerInclude() Spalten konfiguriert werden, die mit INCLUDE verwendet wurden.Before EF Core 3.0, ForSqlServerHasIndex().ForSqlServerInclude() provided a way to configure columns used with INCLUDE.

Neues VerhaltenNew behavior

Ab Version 3.0 wird in EF Core die Nutzung von Include für einen Index auf der relationalen Ebene unterstützt.Starting with EF Core 3.0, using Include on an index is now supported at the relational level. Verwenden Sie HasIndex().ForSqlServerInclude().Use HasIndex().ForSqlServerInclude().

HintergründeWhy

Diese Änderung wurde vorgenommen, um die API für Indizes mit Include an einer zentralen Stelle für alle Datenbankanbieter zusammenzuführen.This change was made to consolidate the API for indexes with Include into one place for all database providers.

Vorbeugende MaßnahmenMitigations

Verwenden Sie wie oben beschrieben die neue API.Use the new API, as shown above.

Metadaten-API-ÄnderungenMetadata API changes

Issue #214Tracking Issue #214

Neues VerhaltenNew behavior

Die folgenden Eigenschaften wurden in Erweiterungsmethoden konvertiert:The following properties were converted to extension methods:

  • IEntityType.QueryFilter -> GetQueryFilter()
  • IEntityType.DefiningQuery -> GetDefiningQuery()
  • IProperty.IsShadowProperty -> IsShadowProperty()
  • IProperty.BeforeSaveBehavior -> GetBeforeSaveBehavior()
  • IProperty.AfterSaveBehavior -> GetAfterSaveBehavior()

HintergründeWhy

Mit dieser Änderung wird die Implementierung der oben genannten Schnittstellen vereinfacht.This change simplifies the implementation of the aforementioned interfaces.

Vorbeugende MaßnahmenMitigations

Verwenden Sie die neuen Erweiterungsmethoden.Use the new extension methods.

Anbieterspezifische Metadaten-API-ÄnderungenProvider-specific Metadata API changes

Issue #214Tracking Issue #214

Neues VerhaltenNew behavior

Die anbieterspezifischen Erweiterungsmethoden werden vereinfacht:The provider-specific extension methods will be flattened out:

  • IProperty.Relational().ColumnName -> IProperty.GetColumnName()
  • IEntityType.SqlServer().IsMemoryOptimized -> IEntityType.IsMemoryOptimized()
  • PropertyBuilder.UseSqlServerIdentityColumn() -> PropertyBuilder.UseIdentityColumn()

HintergründeWhy

Mit dieser Änderung wird die Implementierung der oben genannten Erweiterungsmethoden vereinfacht.This change simplifies the implementation of the aforementioned extension methods.

Vorbeugende MaßnahmenMitigations

Verwenden Sie die neuen Erweiterungsmethoden.Use the new extension methods.

EF Core sendet keine PRAGMA-Anweisungen mehr, um Fremdschlüssel in SQLite zu erzwingenEF Core no longer sends pragma for SQLite FK enforcement

Issue #12151Tracking Issue #12151

Altes VerhaltenOld behavior

Vor Version 3.0 wurden in EF Core PRAGMA foreign_keys = 1-Anweisungen gesendet, wenn eine Verbindung mit SQLite hergestellt wurde.Before EF Core 3.0, EF Core would send PRAGMA foreign_keys = 1 when a connection to SQLite is opened.

Neues VerhaltenNew behavior

Ab Version 3.0 werden in EF Core keine PRAGMA foreign_keys = 1-Anweisungen mehr gesendet, wenn eine Verbindung mit SQLite hergestellt wird.Starting with EF Core 3.0, EF Core no longer sends PRAGMA foreign_keys = 1 when a connection to SQLite is opened.

HintergründeWhy

Diese Änderung wurde vorgenommen, da von EF Core standardmäßig SQLitePCLRaw.bundle_e_sqlite3 verwendet wird. Dadurch ist die Erzwingung von Fremdschlüsseln standardmäßig aktiviert und muss nicht jedes Mal explizit aktiviert werden, wenn eine Verbindung hergestellt wird.This change was made because EF Core uses SQLitePCLRaw.bundle_e_sqlite3 by default, which in turn means that FK enforcement is switched on by default and doesn't need to be explicitly enabled each time a connection is opened.

Vorbeugende MaßnahmenMitigations

Fremdschlüssel sind in SQLitePCLRaw.bundle_e_sqlite3 standardmäßig aktiviert. Dieses Bundle wird standardmäßig von EF Core verwendet.Foreign keys are enabled by default in SQLitePCLRaw.bundle_e_sqlite3, which is used by default for EF Core. In anderen Fällen können Fremdschlüssel durch die Angabe Foreign Keys=True in der Verbindungszeichenfolge aktiviert werden.For other cases, foreign keys can be enabled by specifying Foreign Keys=True in your connection string.

SQLitePCLRaw.bundle_e_sqlite3 ist nun eine Abhängigkeit von Microsoft.EntityFrameworkCore.SqliteMicrosoft.EntityFrameworkCore.Sqlite now depends on SQLitePCLRaw.bundle_e_sqlite3

Altes VerhaltenOld behavior

Vor Version 3.0 wurde von EF Core SQLitePCLRaw.bundle_green verwendet.Before EF Core 3.0, EF Core used SQLitePCLRaw.bundle_green.

Neues VerhaltenNew behavior

Ab Version 3.0 wird von EF Core SQLitePCLRaw.bundle_e_sqlite3 verwendet.Starting with EF Core 3.0, EF Core uses SQLitePCLRaw.bundle_e_sqlite3.

HintergründeWhy

Diese Änderung wurde vorgenommen, damit die unter iOS verwendete Version von SQLite sich konsistent zu Versionen auf anderen Plattformen verhält.This change was made so that the version of SQLite used on iOS consistent with other platforms.

Vorbeugende MaßnahmenMitigations

Konfigurieren Sie Microsoft.Data.Sqlite so, dass ein anderes SQLitePCLRaw-Bundle verwendet wird, um die native SQLite-Version unter iOS zu nutzen.To use the native SQLite version on iOS, configure Microsoft.Data.Sqlite to use a different SQLitePCLRaw bundle.

GUID-Werte werden jetzt als TEXT in SQLite gespeichertGuid values are now stored as TEXT on SQLite

Issue #15078Tracking Issue #15078

Altes VerhaltenOld behavior

GUID-Werte wurden in der Vergangenheit in SQLite als BLOB-Werte gespeichert.Guid values were previously stored as BLOB values on SQLite.

Neues VerhaltenNew behavior

GUID-Werte werden jetzt als TEXT gespeichert.Guid values are now stored as TEXT.

HintergründeWhy

Das Binärformat der GUIDs ist nicht standardisiert.The binary format of Guids is not standardized. Das Speichern der Werte als TEXT führt dazu, dass die Datenbank mit anderen Technologien eher kompatibel ist.Storing the values as TEXT makes the database more compatible with other technologies.

Vorbeugende MaßnahmenMitigations

Sie können vorhandene Datenbanken zum neuen Format migrieren, indem Sie SQL-Code wie den folgenden ausführen:You can migrate existing databases to the new format by executing SQL like the following.

UPDATE MyTable
SET GuidColumn = hex(substr(GuidColumn, 4, 1)) ||
                 hex(substr(GuidColumn, 3, 1)) ||
                 hex(substr(GuidColumn, 2, 1)) ||
                 hex(substr(GuidColumn, 1, 1)) || '-' ||
                 hex(substr(GuidColumn, 6, 1)) ||
                 hex(substr(GuidColumn, 5, 1)) || '-' ||
                 hex(substr(GuidColumn, 8, 1)) ||
                 hex(substr(GuidColumn, 7, 1)) || '-' ||
                 hex(substr(GuidColumn, 9, 2)) || '-' ||
                 hex(substr(GuidColumn, 11, 6))
WHERE typeof(GuidColumn) == 'blob';

Sie können in EF Core auch weiterhin das alte Verhalten verwenden, indem Sie einen Wertkonverter für diese Eigenschaften konfigurieren.In EF Core, you could also continue using the previous behavior by configuring a value converter on these properties.

modelBuilder
    .Entity<MyEntity>()
    .Property(e => e.GuidProperty)
    .HasConversion(
        g => g.ToByteArray(),
        b => new Guid(b));

Microsoft.Data.Sqlite kann weiterhin GUID-Werte aus BLOB- und TEXT-Spalten lesen. Da sich jedoch das Standardformat für Parameter und Konstanten geändert hat, müssen Sie wahrscheinlich Aktionen für die meisten GUID-Szenarios vornehmen.Microsoft.Data.Sqlite remains capable of reading Guid values from both BLOB and TEXT columns; however, since the default format for parameters and constants has changed you'll likely need to take action for most scenarios involving Guids.

Char-Werte werden jetzt als TEXT in SQLite gespeichertChar values are now stored as TEXT on SQLite

Issue #15020Tracking Issue #15020

Altes VerhaltenOld behavior

Char-Werte wurden in der Vergangenheit in SQLite als INTEGER-Werte gespeichert.Char values were previously sored as INTEGER values on SQLite. Der Char-Wert A wurde z.B. als INTEGER-Wert 65 gespeichert.For example, a char value of A was stored as the integer value 65.

Neues VerhaltenNew behavior

Char-Werte werden jetzt als TEXT gespeichert.Char values are now stored as TEXT.

HintergründeWhy

Das Speichern der Werte als TEXT ist naheliegender und führt dazu, dass die Datenbank mit anderen Technologien eher kompatibel ist.Storing the values as TEXT is more natural and makes the database more compatible with other technologies.

Vorbeugende MaßnahmenMitigations

Sie können vorhandene Datenbanken zum neuen Format migrieren, indem Sie SQL-Code wie den folgenden ausführen:You can migrate existing databases to the new format by executing SQL like the following.

UPDATE MyTable
SET CharColumn = char(CharColumn)
WHERE typeof(CharColumn) = 'integer';

Sie können in EF Core auch weiterhin das alte Verhalten verwenden, indem Sie einen Wertkonverter für diese Eigenschaften konfigurieren.In EF Core, you could also continue using the previous behavior by configuring a value converter on these properties.

modelBuilder
    .Entity<MyEntity>()
    .Property(e => e.CharProperty)
    .HasConversion(
        c => (long)c,
        i => (char)i);

Microsoft.Data.Sqlite kann auch weiterhin Zeichenwerte aus INTEGER- und TEXT-Spalten lesen, weshalb es sein kann, dass in einigen Szenarios keine weiteren Maßnahmen erforderlich sind.Microsoft.Data.Sqlite also remains capable of reading character values from both INTEGER and TEXT columns, so certain scenarios may not require any action.

Migrations-IDs werden jetzt mit dem Kalender der invarianten Kultur generiertMigration IDs are now generated using the invariant culture's calendar

Issue #12978Tracking Issue #12978

Altes VerhaltenOld behavior

Migrations-IDs wurden versehentlich mit dem Kalender der aktuellen Kultur generiert.Migration IDs were inadvertently generated using the current culture's calendar.

Neues VerhaltenNew behavior

Migrations-IDs werden jetzt immer mit dem Kalender der invarianten Kultur generiert (gregorianischer Kalender).Migration IDs are now always generated using the invariant culture's calendar (Gregorian).

HintergründeWhy

Die Reihenfolge der Migrationen ist beim Aktualisieren einer Datenbank oder Auflösen von Mergekonflikten wesentlich.The order of migrations is important when updating the database or resolving merge conflicts. Wenn der invariante Kalender verwendet wird, werden Probleme bei der Reihenfolge vermieden, die entstehen, wenn Teammitglieder unterschiedliche Systemkalender verwenden.Using the invariant calendar avoids ordering issues that can result from team members having different system calendars.

Vorbeugende MaßnahmenMitigations

Diese Änderung betrifft jeden Benutzer, der einen Kalender verwendet, der nicht gregorianisch ist und bei dem die Jahreszahl höher als die des gregorianischen Kalenders ist (wie z.B. in der buddhistischen Zeitrechnung).This change affects anyone using a non-Gregorian calendar where the year is greater than the Gregorian calendar (like the Thai Buddhist calendar). Vorhandene Migrations-IDs müssen aktualisiert werden, damit neue Migrationen in der Reihenfolge hinter vorhandenen Migrationen eingeordnet werden.Existing migration IDs will need to be updated so that new migrations are ordered after existing migrations.

Sie können die Migrations-ID im Migration-Attribut in der Designerdatei der Migration finden.The migration ID can be found in the Migration attribute in the migrations' designer files.

 [DbContext(typeof(MyDbContext))]
-[Migration("25620318122820_MyMigration")]
+[Migration("20190318122820_MyMigration")]
 partial class MyMigration
 {

Die Tabelle mit dem Migrationsverlauf muss auch aktualisiert werden.The Migrations history table also needs to be updated.

UPDATE __EFMigrationsHistory
SET MigrationId = CONCAT(LEFT(MigrationId, 4)  - 543, SUBSTRING(MigrationId, 4, 150))

UseRowNumberForPaging wurde entfernt.UseRowNumberForPaging has been removed

Issue #16400Tracking Issue #16400

Altes VerhaltenOld behavior

Vor EF Core 3.0 konnte UseRowNumberForPaging zum Generieren von SQL-Code für die Paginierung verwendet werden, der mit SQL Server 2008 kompatibel ist.Before EF Core 3.0, UseRowNumberForPaging could be used to generate SQL for paging that is compatible with SQL Server 2008.

Neues VerhaltenNew behavior

Ab EF Core 3.0 generiert EF nur noch SQL-Code für die Paginierung, die mit höheren SQL Server-Versionen kompatibel ist.Starting with EF Core 3.0, EF will only generate SQL for paging that is only compatible with later SQL Server versions.

HintergründeWhy

Wir führen diese Änderung ein, weil SQL Server 2008 kein unterstütztes Produkt mehr ist und weil die Aktualisierung dieses Features auf die in EF Core 3.0 vorgenommenen Änderungen an Abfragen ein wichtiger Schritt ist.We are making this change because SQL Server 2008 is no longer a supported product and updating this feature to work with the query changes made in EF Core 3.0 is significant work.

Vorbeugende MaßnahmenMitigations

Es empfiehlt sich, eine Update auf eine neuere Version von SQL Server durchzuführen oder einen höheren Kompatibilitätsgrad zu verwenden, damit der generierte SQL-Code unterstützt wird.We recommend updating to a newer version of SQL Server, or using a higher compatibility level, so that the generated SQL is supported. Wenn dies bei Ihnen nicht möglich ist, fügen Sie einen Kommentar zum Issue ein, und geben Sie alle relevanten Informationen an.That being said, if you are unable to do this, then please comment on the tracking issue with details. Je nach Feedback der Benutzer wird diese Entscheidung möglicherweise noch einmal überprüft.We may revisit this decision based on feedback.

Erweiterungsinformationen und Metadaten aus IDbContextOptionsExtension entferntExtension info/metadata has been removed from IDbContextOptionsExtension

Issue #16119Tracking Issue #16119

Altes VerhaltenOld behavior

IDbContextOptionsExtension enthielt Methoden zum Bereitstellen von Metadaten zur Erweiterung.IDbContextOptionsExtension contained methods for providing metadata about the extension.

Neues VerhaltenNew behavior

Diese Methoden wurden in eine neue abstrakte DbContextOptionsExtensionInfo-Basisklasse verschoben, die von einer neuen IDbContextOptionsExtension.Info-Eigenschaft zurückgegeben werden.These methods have been moved onto a new DbContextOptionsExtensionInfo abstract base class, which is returned from a new IDbContextOptionsExtension.Info property.

HintergründeWhy

In den Releases zwischen 2.0 und 3.0 mussten wir diese Methoden mehrmals ergänzen oder ändern.Over the releases from 2.0 to 3.0 we needed to add to or change these methods several times. Durch die Bereitstellung dieser Methoden in einer neuen abstrakten Basisklasse lassen sich solche Änderungen einfacher einführen, ohne dass es zu Konflikten mit vorhandenen Erweiterungen kommt.Breaking them out into a new abstract base class will make it easier to make these kind of changes without breaking existing extensions.

Vorbeugende MaßnahmenMitigations

Erweiterungen wurden aktualisiert und verwenden das neue Muster.Update extensions to follow the new pattern. Beispiele finden sich in den vielen Implementierungen von IDbContextOptionsExtension für verschiedene Arten von Erweiterungen im EF Core-Quellcode.Examples are found in the many implementations of IDbContextOptionsExtension for different kinds of extensions in the EF Core source code.

LogQueryPossibleExceptionWithAggregateOperator wurde umbenanntLogQueryPossibleExceptionWithAggregateOperator has been renamed

Issue #10985Tracking Issue #10985

ÄnderungChange

RelationalEventId.LogQueryPossibleExceptionWithAggregateOperator wurde umbenannt in RelationalEventId.LogQueryPossibleExceptionWithAggregateOperatorWarning.RelationalEventId.LogQueryPossibleExceptionWithAggregateOperator has been renamed to RelationalEventId.LogQueryPossibleExceptionWithAggregateOperatorWarning.

HintergründeWhy

Die Benennung dieses Warnereignisses wurde an allen anderen Warnereignissen ausgerichtet.Aligns the naming of this warning event with all other warning events.

Vorbeugende MaßnahmenMitigations

Verwenden Sie den neuen Namen.Use the new name. (Beachten Sie, dass sich die Ereignis-ID-Nummer nicht geändert hat.)(Note that the event ID number has not changed.)

Verdeutlichen der API für Einschränkungsnamen von FremdschlüsselnClarify API for foreign key constraint names

Issue #10730Tracking Issue #10730

Altes VerhaltenOld behavior

Vor EF Core 3.0 wurden Einschränkungsnamen von Fremdschlüsseln einfach als „Namen“ bezeichnet.Before EF Core 3.0, foreign key constraint names were referred to as simply the "name". Beispiel:For example:

var constraintName = myForeignKey.Name;

Neues VerhaltenNew behavior

Ab EF Core 3.0 werden Einschränkungsnamen von Fremdschlüsseln nun als „Einschränkungsnamen“ bezeichnet.Starting with EF Core 3.0, foreign key constraint names are now referred to as the "constraint name". Beispiel:For example:

var constraintName = myForeignKey.ConstraintName;

HintergründeWhy

Durch diese Änderung wird Konsistenz für Benennungen in diesem Bereich gewährleistet, und es wird verdeutlicht, dass es sich dabei um den Namen der Fremdschlüsseleinschränkung handelt und nicht um den Spalten- oder Eigenschaftennamen, auf deren Grundlage der Fremdschlüssel definiert ist.This change brings consistency to naming in this area, and also clarifies that this is the name of the foreign key constraint, and not the column or property name that the foreign key is defined on.

Vorbeugende MaßnahmenMitigations

Verwenden Sie den neuen Namen.Use the new name.

„IRelationalDatabaseCreator.HasTables/HasTablesAsync“ ist jetzt öffentlichIRelationalDatabaseCreator.HasTables/HasTablesAsync have been made public

Issue #15997Tracking Issue #15997

Altes VerhaltenOld behavior

Vor EF Core 3.0 waren diese Methoden geschützt.Before EF Core 3.0, these methods were protected.

Neues VerhaltenNew behavior

Ab EF Core 3.0 sind diese Methoden öffentlich.Starting with EF Core 3.0, these methods are public.

HintergründeWhy

Diese Methoden werden von EF verwendet, um zu ermitteln, ob eine Datenbank erstellt wurde, aber leer ist.These methods are used by EF to determine if a database is created but empty. Dies kann auch außerhalb von EF nützlich sein, um zu ermitteln, ob Migrationen angewendet werden sollen oder nicht.This can also be useful from outside EF when determining whether or not to apply migrations.

Vorbeugende MaßnahmenMitigations

Der Zugriff auf Überschreibungen wurde geändert.Change the accessibility of any overrides.

Microsoft.EntityFrameworkCore.Design ist jetzt ein DevelopmentDependency-PaketMicrosoft.EntityFrameworkCore.Design is now a DevelopmentDependency package

Issue #11506Tracking Issue #11506

Altes VerhaltenOld behavior

Vor EF Core 3.0 war Microsoft.EntityFrameworkCore.Design ein reguläres NuGet-Paket, auf dessen Assembly von Projekten verwiesen werden kann, die davon abhängig sind.Before EF Core 3.0, Microsoft.EntityFrameworkCore.Design was a regular NuGet package whose assembly could be referenced by projects that depended on it.

Neues VerhaltenNew behavior

Ab EF Core 3.0 ist es ein DevelopmentDependency-Paket.Starting with EF Core 3.0, it is a DevelopmentDependency package. Das bedeutet, dass die Abhängigkeit nicht transitiv auf andere Projekte übertragen wird und Sie nicht mehr standardmäßig auf die Assembly verweisen können.Which means that the dependency won't flow transitively into other projects, and that you can no longer, by default, reference its assembly.

HintergründeWhy

Dieses Paket ist nur für die Verwendung zur Entwurfszeit konzipiert.This package is only intended to be used at design time. Bereitgestellte Anwendungen sollten nicht darauf verweisen.Deployed applications shouldn't reference it. Die Kennzeichnung des Pakets als DevelopmentDependency unterstreicht diese Empfehlung.Making the package a DevelopmentDependency reinforces this recommendation.

Vorbeugende MaßnahmenMitigations

Wenn Sie auf dieses Paket verweisen müssen, um das Verhalten von EF Core zur Entwurfszeit zu überschreiben, können Sie die Metadaten des PackageReference-Elements in Ihrem Projekt aktualisieren.If you need to reference this package to override EF Core's design-time behavior, you can update update PackageReference item metadata in your project. Wenn transitiv über via Microsoft.EntityFrameworkCore.Tools auf das Paket verwiesen wird, müssen Sie dem Paket eine explizite PackageReference hinzufügen, um seine Metadaten zu ändern.If the package is being referenced transitively via Microsoft.EntityFrameworkCore.Tools, you will need to add an explicit PackageReference to the package to change its metadata.

<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.0.0">
  <PrivateAssets>all</PrivateAssets>
  <!-- Remove IncludeAssets to allow compiling against the assembly -->
  <!--<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>-->
</PackageReference>

SQLitePCL.raw zu Version 2.0.0 aktualisiertSQLitePCL.raw updated to version 2.0.0

Issue #14824Tracking Issue #14824

Altes VerhaltenOld behavior

Microsoft.EntityFrameworkCore.Sqlite war früher von Version 1.1.12 von SQLitePCL.raw abhängig.Microsoft.EntityFrameworkCore.Sqlite previously depended on version 1.1.12 of SQLitePCL.raw.

Neues VerhaltenNew behavior

Wir haben unser Paket aktualisiert, so dass es jetzt von Version 2.0.0 abhängig ist.We've updated our package to depend on version 2.0.0.

HintergründeWhy

Version 2.0.0 von SQLitePCL.raw zielt auf .NET Standard 2.0 ab.Version 2.0.0 of SQLitePCL.raw targets .NET Standard 2.0. Zuvor war .NET Standard 1.1 das Ziel, hierfür war für ein umfassender Funktionsabschluss von transitiven Paketen erforderlich.It previously targeted .NET Standard 1.1 which required a large closure of transitive packages to work.

Vorbeugende MaßnahmenMitigations

SQLitePCL.raw, Version 2.0.0, enthält einige Breaking Changes.SQLitePCL.raw version 2.0.0 includes some breaking changes. Weitere Informationen finden Sie in den Versionshinweisen.See the release notes for details.

NetTopologySuite auf Version 2.0.0 aktualisiertNetTopologySuite updated to version 2.0.0

Issue #14825Tracking Issue #14825

Altes VerhaltenOld behavior

Die Pakete mit räumlichen Daten waren bisher von Version 1.15.1 der NetTopologySuite abhängig.The spatial packages previously depended on version 1.15.1 of NetTopologySuite.

Neues VerhaltenNew behavior

Wir haben unser Paket aktualisiert, so dass es jetzt von Version 2.0.0 abhängig ist.We've update our package to depend on version 2.0.0.

HintergründeWhy

Version 2.0.0 der NetTopologySuite behebt verschiedene Verwendungsprobleme, die von EF Core-Benutzern gemeldet wurden.Version 2.0.0 of NetTopologySuite aims to address several usability issues encountered by EF Core users.

Vorbeugende MaßnahmenMitigations

NetTopologySuite 2.0.0 umfasst einige Breaking Changes.NetTopologySuite version 2.0.0 includes some breaking changes. Weitere Informationen finden Sie in den Versionshinweisen.See the release notes for details.

Microsoft.Data.SqlClient wird statt System.Data.SqlClient verwendetMicrosoft.Data.SqlClient is used instead of System.Data.SqlClient

Issue #15636Tracking Issue #15636

Altes VerhaltenOld behavior

Microsoft.EntityFrameworkCore.SqlServer war zuvor von System.Data.SqlClient abhängig.Microsoft.EntityFrameworkCore.SqlServer previously depended on System.Data.SqlClient.

Neues VerhaltenNew behavior

Das Paket wurde so aktualisiert, dass es jetzt von Microsoft.Data.SqlClient abhängig ist.We've updated our package to depend on Microsoft.Data.SqlClient.

HintergründeWhy

Microsoft SQL Server ist zukünftig der Haupttreiber für den Datenzugriff für SQL Server, und System.Data.SqlClient wird nicht länger der Fokus bei der Entwicklung sein.Microsoft.Data.SqlClient is the flagship data access driver for SQL Server going forward, and System.Data.SqlClient no longer be the focus of development. Einige wichtige Features wie Always Encrypted sind nur in Microsoft.Data.SqlClient verfügbar.Some important features, such as Always Encrypted, are only available on Microsoft.Data.SqlClient.

Vorbeugende MaßnahmenMitigations

Wenn Ihr Code eine direkte Abhängigkeit von System.Data.SqlClient hat, müssen Sie diesen ändern, damit er stattdessen auf Microsoft.Data.SqlClient verweist. Da die beiden Pakete einen hohen Grad an API-Kompatibilität vorweisen, sollte dafür nur eine einfache Paket- und Namespaceänderung erforderlich sein.If your code takes a direct dependency on System.Data.SqlClient, you must change it to reference Microsoft.Data.SqlClient instead; as the two packages maintain a very high degree of API compatibility, this should only be a simple package and namespace change.

Beziehungen mit mehreren mehrdeutigen Selbstverweisen müssen nun konfiguriert werdenMultiple ambiguous self-referencing relationships must be configured

Issue #13573Tracking Issue #13573

Altes VerhaltenOld behavior

Ein Entitätstyp, der über unidirektionale Navigationseigenschaften mit mehreren Selbstverweisen und über übereinstimmende Fremdschlüssel verfügte, wurde bislang fälschlicherweise als einfache Beziehung konfiguriert.An entity type with multiple self-referencing uni-directional navigation properties and matching FKs was incorrectly configured as a single relationship. Beispiel:For example:

public class User 
{
        public Guid Id { get; set; }
        public User CreatedBy { get; set; }
        public User UpdatedBy { get; set; }
        public Guid CreatedById { get; set; }
        public Guid? UpdatedById { get; set; }
}

Neues VerhaltenNew behavior

Dieses Szenario wird nun beim Erstellen von Modellen erkannt. Außerdem wird eine Ausnahme ausgelöst, in der darauf hingewiesen wird, dass das Modell mehrdeutig ist.This scenario is now detected in model building and an exception is thrown indicating that the model is ambiguous.

HintergründeWhy

Das resultierende Modell war mehrdeutig und führte in diesem Fall üblicherweise zu falschen Ergebnissen.The resultant model was ambiguous and will likely usually be wrong for this case.

Vorbeugende MaßnahmenMitigations

Konfigurieren Sie die Beziehung vollständig.Use full configuration of the relationship. Beispiel:For example:

modelBuilder
     .Entity<User>()
     .HasOne(e => e.CreatedBy)
     .WithMany();
 
 modelBuilder
     .Entity<User>()
     .HasOne(e => e.UpdatedBy)
     .WithMany();

DbFunction.Schema ist NULL oder eine leere Zeichenfolge und ist deshalb so konfiguriert, dass es im Standardschema des Modells istDbFunction.Schema being null or empty string configures it to be in model's default schema

Issue #12757Tracking Issue #12757

Altes VerhaltenOld behavior

Eine mit dem Schema als leere Zeichenfolge konfigurierte DbFunction wurde als integrierte Funktion ohne Schema behandelt.A DbFunction configured with schema as an empty string was treated as built-in function without a schema. Der folgende Code ordnet z. B. die CLR-Funktion DatePart der integrierten Funktion DATEPART auf SqlServer zu.For example following code will map DatePart CLR function to DATEPART built-in function on SqlServer.

[DbFunction("DATEPART", Schema = "")]
public static int? DatePart(string datePartArg, DateTime? date) => throw new Exception();

Neues VerhaltenNew behavior

Alle DbFunction-Zuordnungen werden als einer benutzerdefinierten Funktion zugeordnet betrachtet.All DbFunction mappings are considered to be mapped to user defined functions. Daher würde die Funktion durch einen leeren Zeichenfolgenwert in das Standardschema für das Modell eingefügt werden.Hence empty string value would put the function inside the default schema for the model. Dies könnte das Schema sein, das explizit über eine fließende modelBuilder.HasDefaultSchema()- oder anderweitig über eine dbo-API konfiguriert wurde.Which could be the schema configured explicitly via fluent API modelBuilder.HasDefaultSchema() or dbo otherwise.

HintergründeWhy

Weil das Schema vorher leer war, konnte man erreichen, dass die Funktion integriert, aber die Logik nur für SqlServer anwendbar war, wo integrierte Funktionen nicht zu einem Schema gehören.Previously schema being empty was a way to treat that function is built-in but that logic is only applicable for SqlServer where built-in functions do not belong to any schema.

Vorbeugende MaßnahmenMitigations

Konfigurieren Sie die Übersetzung von DbFunction manuell, um Sie einer integrierten Funktion zuzuordnen.Configure DbFunction's translation manually to map it to a built-in function.

modelBuilder
    .HasDbFunction(typeof(MyContext).GetMethod(nameof(MyContext.DatePart)))
    .HasTranslation(args => SqlFunctionExpression.Create("DatePart", args, typeof(int?), null));