Breaking Changes in EF Core 7.0 (EF7)

Auf dieser Seite werden API-Änderungen und Behavior Changes dokumentiert, die bei einem Update von EF Core 6 auf EF Core 7 zu Problemen mit bestehenden Anwendungen führen können. Überprüfen Sie frühere grundlegende Änderungen, wenn sie von einer früheren Version von EF Core aktualisiert werden:

Zielframework

EF Core 7.0 zielt auf .NET 6 ab. Dies bedeutet, dass vorhandene Anwendungen, die auf .NET 6 abzielen, dies weiterhin tun können. Anwendungen für ältere .NET-, .NET Core- und .NET Framework-Versionen müssen .NET 6 oder .NET 7 für die Verwendung von EF Core 7.0 verwenden.

Zusammenfassung

Wichtige Änderung Auswirkungen
Encrypt Standardeinstellung true für SQL Server-Verbindungen Hoch
Einige Warnungen lösen standardmäßig wieder Ausnahmen aus Hoch
SQL Server-Tabellen mit Triggern oder bestimmten berechneten Spalten erfordern jetzt eine spezielle EF Core-Konfiguration Hoch
SQLite-Tabellen mit AFTER-Triggern und virtuellen Tabellen erfordern jetzt eine spezielle EF Core-Konfiguration Hoch
Verwaiste Nachfolger optionaler Beziehungen werden nicht automatisch gelöscht Medium
Die Löschweitergabe wird zwischen Tabellen konfiguriert, wenn die TPT-Zuordnung mit SQL Server verwendet wird Medium
Höhere Wahrscheinlichkeit der Fehler „ausgelastet/gesperrt“ in SQLite, wenn keine Write-Ahead-Protokollierung verwendet wird Medium
Wichtige Eigenschaften müssen möglicherweise mit einem Anbieterwertevergleich konfiguriert werden Niedrig
CHECK-Einschränkungen und andere Tabellenfacetten werden jetzt für die Tabelle konfiguriert Niedrig
Navigationen aus neuen Entitäten zu gelöschten Entitäten sind nicht behoben Niedrig
Die Verwendung von FromSqlRaw und verwandter Methoden des falschen Anbieters löst aus Niedrig
Gerüstetes OnConfiguring ruft IsConfigured nicht mehr ab Niedrig

Änderungen mit hoher Auswirkung

Encrypt geht standardmäßig auf true für SQL Server-Verbindungen zurück

Tracking-Problem: SqlClient #1210

Wichtig

Dies ist eine schwerwiegende Breaking Change im Microsoft.Data.SqlClient-Paket. Es gibt nichts, was in EF Core getan werden kann, um diese Änderung wiederherzustellen oder zu mindern. Bitte senden Sie Ihr Feedback an das GitHub-Repository „Microsoft.Data.SqlClient“, oder wenden Sie sich an einen Microsoft-Supportmitarbeiter, um Antworten auf Ihre Fragen oder Hilfe zu erhalten.

Altes Verhalten

SqlClient-Verbindungszeichenfolgen verwenden standardmäßig Encrypt=False. Dies ermöglicht Verbindungen auf Entwicklungscomputern, auf denen der lokale Server kein gültiges Zertifikat besitzt.

Neues Verhalten

SqlClient-Verbindungszeichenfolgen verwenden standardmäßig Encrypt=True. Dies bedeutet Folgendes:

  • Der Server muss mit seinem Zertifikat konfiguriert werden
  • Der Client muss diesem Zertifikat vertrauen

Wenn diese Bedingungen nicht erfüllt sind, wird ein SqlException-Fehler ausgelöst. Beispiel:

Eine Verbindung mit dem Server wurde erfolgreich hergestellt, aber dann trat während des Anmeldevorgangs ein Fehler auf. (Anbieter: SSL-Anbieter, Fehler: 0 – Die Zertifikatkette wurde von einer Zertifizierungsstelle ausgestellt, die nicht vertrauenswürdig ist.)

Warum?

Diese Änderung wurde vorgenommen, um sicherzustellen, dass entweder die Verbindung sicher ist oder die Anwendung keine Verbindung herstellen kann.

Gegenmaßnahmen

Es gibt drei Möglichkeiten fortzufahren:

  1. Installieren Sie ein gültiges Zertifikat auf dem Server. Beachten Sie, dass dies ein beteiligter Prozess ist und ein Zertifikat erhält und sicherstellt, dass es von einer vom Client vertrauenswürdigen Zertifizierungsstelle signiert wird.
  2. Wenn der Server über ein Zertifikat verfügt, dem der Client aber nicht vertraut, dann kann TrustServerCertificate=True die normalen Vertrauensmechanismen umgehen.
  3. Fügen Sie der Verbindungszeichenfolge explizit Encrypt=False hinzu.

Warnung

Optionen 2 und 3 lassen den Server in einem potenziell unsicheren Zustand.

Einige Warnungen lösen ausnahmen standardmäßig erneut aus

Nachverfolgung von Issue 29069

Altes Verhalten

In EF Core 6.0 bedeutete ein Fehler im SQL Server-Anbieter, dass einige Warnungen, die zum Auslösen von Ausnahmen konfiguriert sind, stattdessen protokolliert wurden, aber keine Ausnahmen auslösen. Diese Warnungen sind:

EventId Beschreibung
RelationalEventId.AmbientTransactionWarning Eine Anwendung hat möglicherweise erwartet, dass eine Umgebungstransaktion verwendet wird, wenn sie tatsächlich ignoriert wurde.
RelationalEventId.IndexPropertiesBothMappedAndNotMappedToTable Ein Index spezifiziert Eigenschaften, von denen einige einer Spalte in einer Tabelle zugeordnet sind und einige nicht.
RelationalEventId.IndexPropertiesMappedToNonOverlappingTables Ein Index gibt Eigenschaften an, die sich auf Spalten in nicht überlappenden Tabellen beziehen.
RelationalEventId.ForeignKeyPropertiesMappedToUnrelatedTables Ein Fremdschlüssel gibt Eigenschaften an, die sich nicht auf die Bezugstabellen beziehen.

Neues Verhalten

Ab EF Core 7.0 führen diese Warnungen standardmäßig wieder zu einer Ausnahme.

Warum?

Dies sind Probleme, die sehr wahrscheinlich auf einen Fehler im Anwendungscode hinweisen, der behoben werden sollte.

Gegenmaßnahmen

Beheben Sie das zugrunde liegende Problem, das der Grund für die Warnung ist.

Alternativ kann die Warnstufe so geändert werden, dass sie nur protokolliert oder vollständig unterdrückt wird. Beispiel:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .ConfigureWarnings(b => b.Ignore(RelationalEventId.AmbientTransactionWarning));

SQL Server-Tabellen mit Triggern oder bestimmten berechneten Spalten erfordern jetzt eine spezielle EF Core-Konfiguration

Nachverfolgung von Issue 27372

Altes Verhalten

In früheren Versionen des SQL Server-Anbieters wurden Änderungen über eine weniger effiziente Technik gespeichert, die immer funktionierte.

Neues Verhalten

Standardmäßig speichert EF Core jetzt Änderungen über eine wesentlich effizientere Technik; leider wird diese Technik auf SQL Server nicht unterstützt, wenn die Zieltabelle Datenbank-Trigger oder bestimmte Arten von berechneten Spalten hat. Weitere Informationen finden Sie in der SQL Server-Dokumentation.

Warum?

Die mit der neuen Methode verbundenen Leistungsverbesserungen sind so bedeutend, dass es wichtig ist, sie den Benutzern standardmäßig zur Verfügung zu stellen. Gleichzeitig schätzen wir die Verwendung von Datenbanktriggern oder der betroffenen berechneten Spalten in EF Core-Anwendungen als so gering ein, dass die negativen Auswirkungen der Änderungen durch den Leistungsgewinn aufgewogen werden.

Gegenmaßnahmen

Ab EF Core 8.0 kann explizit konfiguriert werden, ob die „OUTPUT“-Klausel verwendet wird oder nicht. Zum Beispiel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable(tb => tb.UseSqlOutputClause(false));
}

In EF7 oder höher: Wenn die Zieltabelle einen Auslöser hat, können Sie EF Core dies mitteilen, und EF greift dann auf die vorherige, weniger effiziente Technik zurück. Dazu muss der entsprechende Entitätstyp wie folgt konfiguriert werden:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable(tb => tb.HasTrigger("SomeTrigger"));
}

Beachten Sie, dass dadurch EF Core den Trigger nicht wirklich erstellt oder verwaltet – es informiert EF Core derzeit nur, dass Trigger in der Tabelle vorhanden sind. Infolgedessen kann jeder Auslösername verwendet werden. Die Angabe eines Auslösers kann verwendet werden, um das alte Verhalten wiederherzustellen, auch wenn kein Auslöser in der Tabelle vorhanden ist.

Wenn die meisten oder alle Ihre Tabellen über Trigger verfügen, können Sie auf die Verwendung der neueren, effizienten Technik für alle Tabellen Ihres Modells verzichten, indem Sie die folgende Modellbaukonvention verwenden:

public class BlankTriggerAddingConvention : IModelFinalizingConvention
{
    public virtual void ProcessModelFinalizing(
        IConventionModelBuilder modelBuilder,
        IConventionContext<IConventionModelBuilder> context)
    {
        foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
        {
            var table = StoreObjectIdentifier.Create(entityType, StoreObjectType.Table);
            if (table != null
                && entityType.GetDeclaredTriggers().All(t => t.GetDatabaseName(table.Value) == null)
                && (entityType.BaseType == null
                    || entityType.GetMappingStrategy() != RelationalAnnotationNames.TphMappingStrategy))
            {
                entityType.Builder.HasTrigger(table.Value.Name + "_Trigger");
            }

            foreach (var fragment in entityType.GetMappingFragments(StoreObjectType.Table))
            {
                if (entityType.GetDeclaredTriggers().All(t => t.GetDatabaseName(fragment.StoreObject) == null))
                {
                    entityType.Builder.HasTrigger(fragment.StoreObject.Name + "_Trigger");
                }
            }
        }
    }
}

Verwenden Sie die Konvention für Ihr DbContext, indem Sie ConfigureConventions außer Kraft setzen:

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Conventions.Add(_ => new BlankTriggerAddingConvention());
}

Dadurch wird HasTrigger für alle Tabellen Ihres Modells aufgerufen, so dass Sie dies nicht für jede einzelne Tabelle manuell tun müssen.

SQLite-Tabellen mit AFTER-Triggern und virtuellen Tabellen erfordern jetzt eine spezielle EF Core-Konfiguration

Nachverfolgung von Issue 29916

Altes Verhalten

In früheren Versionen des SQLite-Anbieters wurden Änderungen über eine weniger effiziente Technik gespeichert, die immer funktionierte.

Neues Verhalten

Standardmäßig speichert EF Core Änderungen mithilfe der RETURNING-Klausel jetzt mithilfe einer effizienteren Technik. Leider wird diese Technik für SQLite nicht unterstützt, wenn die Zieltabelle über Datenbank-AFTER-Trigger verfügt, virtuell ist oder ältere Versionen von SQLite verwendet werden. Weitere Details finden Sie in der Dokumentation zu SQLite.

Warum?

Die mit der neuen Methode verbundenen Vereinfachungen und Leistungsverbesserungen sind so bedeutend, dass es wichtig ist, sie den Benutzern standardmäßig zur Verfügung zu stellen. Gleichzeitig schätzen wir die Verwendung von Datenbanktriggern und virtuellen Tabellen in EF Core-Anwendungen als so gering ein, dass die negativen Auswirkungen der Änderungen durch den Leistungsgewinn aufgewogen werden.

Gegenmaßnahmen

In EF Core 8.0 wurde die UseSqlReturningClause-Methode eingeführt, um explizit auf das ältere, weniger effiziente SQL zurückzugreifen. Zum Beispiel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable(tb => tb.UseSqlReturningClause(false));
}

Wenn Sie noch EF Core 7.0 verwenden, können Sie den alten Mechanismus für die gesamte Anwendung wiederherstellen, indem Sie den folgenden Code in Ihre Kontextkonfiguration einfügen:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlite(...)
        .ReplaceService<IUpdateSqlGenerator, SqliteLegacyUpdateSqlGenerator>();

Änderungen mit mittlerer Auswirkung

Verwaiste Nachfolger optionaler Beziehungen werden nicht automatisch gelöscht

Nachverfolgung von Issue 27217

Altes Verhalten

Eine Beziehung ist optional, wenn der Fremdschlüssel Nullwerte zulässt. Durch Festlegen des Fremdschlüssels auf NULL kann die abhängige Entität ohne zugehörige Prinzipalentität vorhanden sein. Optionale Beziehungen können für die Verwendung von Löschweitergaben konfiguriert werden, obwohl dies nicht die Standardeinstellung ist.

Eine optionale abhängige Datei kann von ihrer Hauptdatei abgetrennt werden, indem entweder ihr Fremdschlüssel auf NULL gesetzt oder die Navigation zu oder von ihr gelöscht wird. In EF Core 6.0 würde dies dazu führen, dass die abhängige Nachricht gelöscht wird, wenn die Beziehung für die Löschweitergabe konfiguriert wurde.

Neues Verhalten

Ab EF Core 7.0 wird der abhängige Benutzer nicht mehr gelöscht. Beachten Sie, dass beim Löschen des Prinzipals auch die abhängigen Daten gelöscht werden, da für die Beziehung eine Löschweitergabe konfiguriert ist.

Warum?

Die abhängige Entität kann auch ohne Beziehung zu einem Prinzipal existieren, so dass eine Trennung der Beziehung nicht zur Löschung der Entität führen sollte.

Gegenmaßnahmen

Die abhängigen Elemente können explizit gelöscht werden:

context.Remove(blog);

Oder SaveChanges kann außer Kraft gesetzt oder abgefangen werden, um abhängige Personen ohne prinzipiellen Bezug zu löschen. Beispiel:

context.SavingChanges += (c, _) =>
    {
        foreach (var entry in ((DbContext)c!).ChangeTracker
            .Entries<Blog>()
            .Where(e => e.State == EntityState.Modified))
        {
            if (entry.Reference(e => e.Author).CurrentValue == null)
            {
                entry.State = EntityState.Deleted;
            }
        }
    };

Die Löschweitergabe wird zwischen Tabellen konfiguriert, wenn die TPT-Zuordnung mit SQL Server verwendet wird

Nachverfolgung von Issue 28532

Altes Verhalten

Beim Zuordnen einer Vererbungshierarchie mithilfe der TPT-Strategie muss die Basistabelle unabhängig vom tatsächlichen Typ dieser Entität eine Zeile für jede gespeicherte Entität enthalten. Beim Löschen der Zeile in der Basistabelle sollten Zeilen in allen anderen Tabellen gelöscht werden. EF Core konfiguriert dafür eine Löschweitergabe.

In EF Core 6.0 bedeutete ein Fehler im SQL Server-Datenbankanbieter, dass diese Löschweitergaben nicht erstellt wurden.

Neues Verhalten

Ab EF Core 7.0 werden die Löschweitergaben jetzt für SQL Server genauso wie für andere Datenbanken erstellt.

Warum?

Durch Löschweitergabe aus der Basistabelle an die Untertabellen in TPT kann eine Entität gelöscht werden, indem sie die Zeile in der Basistabelle löscht.

Gegenmaßnahmen

In den meisten Fällen sollte diese Änderung keine Probleme verursachen. SQL Server ist jedoch sehr restriktiv, wenn zwischen Tabellen mehrere kaskadierende Verhaltensweisen konfiguriert sind. Dies bedeutet, dass SQL Server möglicherweise den folgenden Fehler generiert, wenn eine kaskadierende Beziehung zwischen Tabellen in der TPT-Zuordnung vorhanden ist:

Microsoft.Data.SqlClient.SqlException: Die LÖSCHEN-Anweisung ist mit der REFERENZ-Einschränkung „FK_Blogs_People_OwnerId“ in Konflikt geraten. Der Konflikt ist in der Spalte „OwnerId“ der Tabelle „dbo.Blogs“ in der Datenbank „Scratch“ aufgetreten. Die Anweisung wurde beendet.

Mit diesem Modell wird beispielsweise ein Zyklus von kaskadierenden Beziehungen erstellt:

[Table("FeaturedPosts")]
public class FeaturedPost : Post
{
    public int ReferencePostId { get; set; }
    public Post ReferencePost { get; set; } = null!;
}

[Table("Posts")]
public class Post
{
    public int Id { get; set; }
    public string? Title { get; set; }
    public string? Content { get; set; }
}

Einer dieser Elemente muss so konfiguriert werden, dass keine Löschweitergaben auf dem Server verwendet werden. So ändern Sie beispielsweise die explizite Beziehung:

modelBuilder
    .Entity<FeaturedPost>()
    .HasOne(e => e.ReferencePost)
    .WithMany()
    .OnDelete(DeleteBehavior.ClientCascade);

Oder um die implizite Beziehung zu ändern, die für die TPT-Zuordnung erstellt wurde:

modelBuilder
    .Entity<FeaturedPost>()
    .HasOne<Post>()
    .WithOne()
    .HasForeignKey<FeaturedPost>(e => e.Id)
    .OnDelete(DeleteBehavior.ClientCascade);

Höhere Wahrscheinlichkeit der Fehler „ausgelastet/gesperrt“ in SQLite, wenn keine Write-Ahead-Protokollierung verwendet wird

Altes Verhalten

In früheren Versionen des SQLite-Anbietenden wurden Änderungen mithilfe einer weniger effizienten Technik gespeichert, die automatisch wiederholen konnte, wenn die Tabelle gesperrt/ausgelastet und die Write-Ahead-Protokollierung nicht aktiviert war.

Neues Verhalten

Standardmäßig speichert EF Core Änderungen mithilfe der RETURNING-Klausel jetzt mithilfe einer effizienteren Technik. Leider kann diese Technik nicht automatisch wiederholen, wenn der Status „ausgelastet/gesperrt“ lautet. In einer Multithreadanwendung (z. B. einer Web-App), die keine Write-Ahead-Protokollierung verwendet, treten diese Fehler häufig auf.

Warum?

Die mit der neuen Methode verbundenen Vereinfachungen und Leistungsverbesserungen sind so bedeutend, dass es wichtig ist, sie den Benutzern standardmäßig zur Verfügung zu stellen. Datenbanken, die von EF Core erstellt wurden, aktivieren standardmäßig auch die Write-Ahead-Protokollierung. Das SQLite-Team empfiehlt außerdem, die Write-Ahead-Protokollierung standardmäßig zu aktivieren.

Gegenmaßnahmen

Wenn möglich, sollten Sie die Write-Ahead-Protokollierung für Ihre Datenbank aktivieren. Wenn Ihre Datenbank von EF erstellt wurde, sollte dies bereits der Fall sein. Wenn nicht, können Sie die Write-Ahead-Protokollierung aktivieren, indem Sie den folgenden Befehl ausführen.

PRAGMA journal_mode = 'wal';

Wenn Sie die Write-Ahead-Protokollierung aus irgendeinem Grund nicht aktivieren können, können Sie den alten Mechanismus für die gesamte Anwendung wiederherstellen, indem Sie den folgenden Code in Ihre Kontextkonfiguration einfügen:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlite(...)
        .ReplaceService<IUpdateSqlGenerator, SqliteLegacyUpdateSqlGenerator>();

Änderungen mit geringer Auswirkung

Wichtige Eigenschaften müssen möglicherweise mit einem Anbieterwertevergleich konfiguriert werden

Nachverfolgung von Issue 27738

Altes Verhalten

In EF Core 6.0 wurden Schlüsselwerte, die direkt aus den Eigenschaften von Entitätstypen entnommen wurden, zum Vergleich von Schlüsselwerten beim Speichern von Änderungen verwendet. Dadurch werden alle benutzerdefinierten Wertvergleiche verwendet, die für diese Eigenschaften konfiguriert sind.

Neues Verhalten

Ab EF Core 7.0 werden Datenbankwerte für diese Vergleiche verwendet. In den allermeisten Fällen funktioniert das einfach. Wenn jedoch für die Eigenschaften ein benutzerdefinierter Wertevergleich verwendet wurde und dieser Wertevergleich nicht auf die Datenbankwerte angewendet werden kann, kann ein „Anbieterwertevergleich“ erforderlich sein, wie unten dargestellt.

Warum?

Verschiedene Entitätsaufteilungen und Tabellenaufteilung können zu mehreren Eigenschaften führen, die derselben Datenbankspalte zugeordnet sind, und umgekehrt. Dies erfordert, dass Werte nach der Konvertierung in einen Wert verglichen werden, der in der Datenbank verwendet wird.

Gegenmaßnahmen

Konfigurieren Sie einen Anbieterwertvergleich. Betrachten Sie beispielsweise den Fall, in dem ein Wertobjekt als Schlüssel verwendet wird, und der Wertevergleich für diesen Schlüssel Zeichenfolgenvergleiche mit Groß-/Kleinschreibung verwendet:

var blogKeyComparer = new ValueComparer<BlogKey>(
    (l, r) => string.Equals(l.Id, r.Id, StringComparison.OrdinalIgnoreCase),
    v => v.Id.ToUpper().GetHashCode(),
    v => v);

var blogKeyConverter = new ValueConverter<BlogKey, string>(
    v => v.Id,
    v => new BlogKey(v));

modelBuilder.Entity<Blog>()
    .Property(e => e.Id).HasConversion(
        blogKeyConverter, blogKeyComparer);

Die Datenbankwerte (Zeichenfolgen) können den für BlogKey-Typen definierten Wertevergleich nicht direkt verwenden. Daher muss ein Anbieterwertevergleich für Zeichenfolgenvergleiche zwischen Groß- und Kleinschreibung konfiguriert werden:

var caseInsensitiveComparer = new ValueComparer<string>(
    (l, r) => string.Equals(l, r, StringComparison.OrdinalIgnoreCase),
    v => v.ToUpper().GetHashCode(),
    v => v);

var blogKeyComparer = new ValueComparer<BlogKey>(
    (l, r) => string.Equals(l.Id, r.Id, StringComparison.OrdinalIgnoreCase),
    v => v.Id.ToUpper().GetHashCode(),
    v => v);

var blogKeyConverter = new ValueConverter<BlogKey, string>(
    v => v.Id,
    v => new BlogKey(v));

modelBuilder.Entity<Blog>()
    .Property(e => e.Id).HasConversion(
        blogKeyConverter, blogKeyComparer, caseInsensitiveComparer);

CHECK-Einschränkungen und andere Tabellenfacetten werden jetzt für die Tabelle konfiguriert

Nachverfolgung von Issue 28205

Altes Verhalten

In EF Core 6.0 wurden HasCheckConstraint, HasComment und IsMemoryOptimized direkt für den Entitätstyp-Generator aufgerufen. Beispiel:

modelBuilder
    .Entity<Blog>()
    .HasCheckConstraint("CK_Blog_TooFewBits", "Id > 1023");

modelBuilder
    .Entity<Blog>()
    .HasComment("It's my table, and I'll delete it if I want to.");

modelBuilder
    .Entity<Blog>()
    .IsMemoryOptimized();

Neues Verhalten

Ab EF Core 7.0 werden diese Methoden stattdessen für den Tabellen-Generator aufgerufen:

modelBuilder
    .Entity<Blog>()
    .ToTable(b => b.HasCheckConstraint("CK_Blog_TooFewBits", "Id > 1023"));

modelBuilder
    .Entity<Blog>()
    .ToTable(b => b.HasComment("It's my table, and I'll delete it if I want to."));

modelBuilder
    .Entity<Blog>()
    .ToTable(b => b.IsMemoryOptimized());

Die vorhandenen Methoden wurden als Obsolete gekennzeichnet. Sie haben derzeit das gleiche Verhalten wie die neuen Methoden, werden aber in einer zukünftigen Version entfernt.

Warum?

Diese Facetten gelten nur für Tabellen. Sie werden nicht auf zugeordnete Ansichten, Funktionen oder gespeicherte Prozeduren angewendet.

Gegenmaßnahmen

Verwenden Sie die Methoden des Tabellengenerators, wie oben gezeigt.

Nachverfolgung von Issue 28249

Altes Verhalten

Wenn in EF Core 6.0 eine neue Entität entweder über eine Nachverfolgungsabfrage oder durch Anhängen an DbContext nachverfolgt wird, dann werden Navigationen zu und von verwandten Entitäten im Deleted-Zustandeingerichtet.

Neues Verhalten

Ab EF Core 7.0 sind Navigationen zu und von Deleted-Entitäten nicht behoben.

Warum?

Sobald eine Entität als Deleted markiert ist, macht es selten Sinn, sie mit nicht gelöschten Entitäten zu verknüpfen.

Gegenmaßnahmen

Sie können Entitäten abfragen oder anhängen, bevor Sie sie als Deleted markieren, oder manuell Navigationseigenschaften zu und von der gelöschten Entität festlegen.

Nachverfolgung von Issue 26502

Altes Verhalten

In EF Core 6.0 kann die Verwendung der Azure Cosmos DB-Erweiterungsmethode FromSqlRaw bei Verwendung eines relationalen Anbieters oder der relationalen Erweiterungsmethode FromSqlRaw bei Verwendung des Azure Cosmos DB-Anbieters im Hintergrund fehlschlagen. Ebenso ist die Verwendung relationaler Methoden für den In-Memory-Anbieter eine automatische Nulloperation.

Neues Verhalten

Ab EF Core 7.0 wird bei Verwendung einer Erweiterungsmethode, die für einen Anbieter entwickelt wurde, bei einem anderen Anbieter eine Ausnahme ausgelöst.

Warum?

Die richtige Erweiterungsmethode muss verwendet werden, damit sie in allen Situationen ordnungsgemäß funktioniert.

Gegenmaßnahmen

Verwenden Sie die richtige Erweiterungsmethode für den verwendeten Anbieter. Wenn auf mehrere Anbieter verwiesen wird, rufen Sie die Erweiterungsmethode als statische Methode auf. Beispiel:

var result = CosmosQueryableExtensions.FromSqlRaw(context.Blogs, "SELECT ...").ToList();

Oder:

var result = RelationalQueryableExtensions.FromSqlRaw(context.Blogs, "SELECT ...").ToList();

Gerüstetes OnConfiguring ruft IsConfigured nicht mehr ab

Nachverfolgung von Issue 4274

Altes Verhalten

In EF Core 6.0 enthielt der Typ DbContext, der aus einer bestehenden Datenbank gerüstet wurde, einen Aufruf an IsConfigured. Beispiel:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
        optionsBuilder.UseNpgsql("MySecretConnectionString");
    }
}

Neues Verhalten

Ab EF Core 7.0 ist der Aufruf an IsConfigured nicht mehr enthalten.

Warum?

Es gibt sehr begrenzte Szenarien, in denen der Datenbankanbieter in einigen Fällen in Ihrem DbContext konfiguriert ist, aber nur, wenn der Kontext noch nicht konfiguriert ist. Wenn Sie OnConfiguring hier lassen, ist es wahrscheinlicher, dass trotz der Kompilierwarnung eine Zeichenfolge mit vertraulichen Informationen im Code verbleibt. Die zusätzliche Sicherheit und der sauberere Code, die sich aus der Entfernung dieser Methode ergeben, wurden als lohnenswert erachtet, zumal das --no-onconfiguring- (.NET CLI) oder -NoOnConfiguring-Flag (Visual Studio Package Manager Console) verwendet werden kann, um die Gerüstbildung der OnConfiguring-Methode zu verhindern, und dass es anpassbare Vorlagen gibt, um IsConfigured wieder hinzuzufügen, wenn es wirklich benötigt wird.

Gegenmaßnahmen

Entweder:

  • Verwenden Sie das Argument --no-onconfiguring (.NET CLI) oder -NoOnConfiguring (Visual Studio Package Manager Console), wenn Sie aus einer vorhandenen Datenbank rüsten.
  • Passen Sie die T4-Vorlagen an, um den Aufruf an IsConfigured wieder hinzuzufügen.