Änderungs Erkennung und BenachrichtigungenChange Detection and Notifications

Jede DbContext Instanz verfolgt Änderungen, die an Entitäten vorgenommen wurden.Each DbContext instance tracks changes made to entities. Diese überwachten Entitäten Steuern wiederum die Änderungen an der Datenbank, wenn SaveChanges aufgerufen wird.These tracked entities in turn drive the changes to the database when SaveChanges is called. Dies wird in Änderungsnachverfolgung in EF Corebehandelt. in diesem Dokument wird davon ausgegangen, dass Entitäts Zustände und Grundlagen der Entity Framework Core (EF Core)-Änderungs Nachverfolgung verstanden werden.This is covered in Change Tracking in EF Core, and this document assumes that entity states and the basics of Entity Framework Core (EF Core) change tracking are understood.

Für das Nachverfolgen von Eigenschaften-und Beziehungs Änderungen ist es erforderlich, dass dbcontext diese Änderungen erkennen kann.Tracking property and relationship changes requires that the DbContext is able to detect these changes. In diesem Dokument wird erläutert, wie diese Erkennung erfolgt. Außerdem wird erläutert, wie Sie Eigenschafts Benachrichtigungen oder Proxys für die Änderungs Nachverfolgung verwenden können, um eine sofortige Erkennung von ÄnderungenThis document covers how this detection happens, as well as how to use property notifications or change-tracking proxies to force immediate detection of changes.

Tipp

Sie können den gesamten Code in diesem Dokument ausführen und Debuggen, indem Sie den Beispielcode von GitHub herunterladen.You can run and debug into all the code in this document by downloading the sample code from GitHub.

Änderungsnachverfolgung für MomentaufnahmenSnapshot change tracking

Standardmäßig erstellt EF Core eine Momentaufnahme der Eigenschaftswerte jeder Entität, wenn Sie zuerst von einer dbcontext-Instanz nachverfolgt wird.By default, EF Core creates a snapshot of every entity's property values when it is first tracked by a DbContext instance. Die in dieser Momentaufnahme gespeicherten Werte werden dann mit den aktuellen Werten der Entität verglichen, um zu bestimmen, welche Eigenschaftswerte geändert wurden.The values stored in this snapshot are then compared against the current values of the entity in order to determine which property values have changed.

Diese Erkennung von Änderungen erfolgt, wenn SaveChanges aufgerufen wird, um sicherzustellen, dass alle geänderten Werte erkannt werden, bevor Updates an die Datenbank gesendet werden.This detection of changes happens when SaveChanges is called to ensure all changed values are detected before sending updates to the database. Die Erkennung von Änderungen wird jedoch auch zu anderen Zeiten durchgeführt, um sicherzustellen, dass die Anwendung mit aktuellen Überwachungsinformationen arbeitet.However, the detection of changes also happens at other times to ensure the application is working with up-to-date tracking information. Die Erkennung von Änderungen kann jederzeit durch Aufrufen von erzwungen werden ChangeTracker.DetectChanges() .Detection of changes can be forced at any time by calling ChangeTracker.DetectChanges().

Wenn die Änderungs Erkennung erforderlich istWhen change detection is needed

Die Erkennung von Änderungen wird benötigt, wenn eine Eigenschaft oder Navigation geändert wurde , ohne EF Core zu verwenden, um diese Änderung vorzunehmen.Detection of changes is needed when a property or navigation has been changed without using EF Core to make this change. Sie können z. b. Blogs und Beiträge laden und dann Änderungen an diesen Entitäten vornehmen:For example, consider loading blogs and posts and then making changes to these entities:

using var context = new BlogsContext();
var blog = context.Blogs.Include(e => e.Posts).First(e => e.Name == ".NET Blog");

// Change a property value
blog.Name = ".NET Blog (Updated!)";

// Add a new entity to a navigation
blog.Posts.Add(
    new Post
    {
        Title = "What’s next for System.Text.Json?", Content = ".NET 5.0 was released recently and has come with many..."
    });

Console.WriteLine(context.ChangeTracker.DebugView.LongView);
context.ChangeTracker.DetectChanges();
Console.WriteLine(context.ChangeTracker.DebugView.LongView);

Wenn Sie die Debugansicht der Änderungs Nachverfolgung vor dem Aufruf von ChangeTracker.DetectChanges() anzeigen, wird angezeigt, dass die vorgenommenen Änderungen nicht erkannt wurden und daher nicht in den Entitäts Zuständen und geänderten Eigenschaften Daten widergespiegelt werden:Looking at the change tracker debug view before calling ChangeTracker.DetectChanges() shows that the changes made have not been detected and hence are not reflected in the entity states and modified property data:

Blog {Id: 1} Unchanged
  Id: 1 PK
  Name: '.NET Blog (Updated!)' Originally '.NET Blog'
  Posts: [{Id: 1}, {Id: 2}, <not found>]
Post {Id: 1} Unchanged
  Id: 1 PK
  BlogId: 1 FK
  Content: 'Announcing the release of EF Core 5.0, a full featured cross...'
  Title: 'Announcing the Release of EF Core 5.0'
  Blog: {Id: 1}
Post {Id: 2} Unchanged
  Id: 2 PK
  BlogId: 1 FK
  Content: 'F# 5 is the latest version of F#, the functional programming...'
  Title: 'Announcing F# 5'
  Blog: {Id: 1}

Insbesondere ist der Status des Blogeintrags immer noch Unchanged , und der neue Beitrag wird nicht als nach verfolgte Entität angezeigt.Specifically, the state of the blog entry is still Unchanged, and the new post does not appear as a tracked entity. (Die aKlugen wird bemerken, dass Eigenschaften ihre neuen Werte melden, auch wenn diese Änderungen von EF Core noch nicht erkannt wurden.(The astute will notice properties report their new values, even though these changes have not yet been detected by EF Core. Dies liegt daran, dass in der Debugansicht aktuelle Werte direkt aus der Entitäts Instanz gelesen werden.)This is because the debug view is reading current values directly from the entity instance.)

Vergleichen Sie dies mit der Debugansicht nach dem Aufrufen von "DetectChanges":Contrast this with the debug view after calling DetectChanges:

Blog {Id: 1} Modified
  Id: 1 PK
  Name: '.NET Blog (Updated!)' Modified Originally '.NET Blog'
  Posts: [{Id: 1}, {Id: 2}, {Id: -2147482643}]
Post {Id: -2147482643} Added
  Id: -2147482643 PK Temporary
  BlogId: 1 FK
  Content: '.NET 5.0 was released recently and has come with many...'
  Title: 'What's next for System.Text.Json?'
  Blog: {Id: 1}
Post {Id: 1} Unchanged
  Id: 1 PK
  BlogId: 1 FK
  Content: 'Announcing the release of EF Core 5.0, a full featured cross...'
  Title: 'Announcing the Release of EF Core 5.0'
  Blog: {Id: 1}
Post {Id: 2} Unchanged
  Id: 2 PK
  BlogId: 1 FK
  Content: 'F# 5 is the latest version of F#, the functional programming...'
  Title: 'Announcing F# 5'
  Blog: {Id: 1}

Der Blog ist nun ordnungsgemäß als gekennzeichnet, Modified und der neue Beitrag wurde erkannt und nachverfolgt Added .Now the blog is correctly marked as Modified and the new post has been detected and is tracked as Added.

Zu Beginn dieses Abschnitts haben wir festgestellt, dass das Erkennen von Änderungen erforderlich ist, wenn nicht die Verwendung von EF Core zum vornehmen der Änderung verwendet wird.At the start of this section we stated that detecting changes is needed when not using using EF Core to make the change. Dies geschieht im obigen Code.This is what is happening in the code above. Das heißt, die Änderungen an der Eigenschaft und der Navigation werden direkt auf den Entitäts Instanzen vorgenommen, nicht mithilfe von EF Core Methoden.That is, the changes to the property and navigation are made directly on the entity instances, and not by using any EF Core methods.

Vergleichen Sie dies mit dem folgenden Code, der die Entitäten auf die gleiche Weise ändert, aber dieses Mal EF Core Methoden verwendet:Contrast this to the following code which modifies the entities in the same way, but this time using EF Core methods:

using var context = new BlogsContext();
var blog = context.Blogs.Include(e => e.Posts).First(e => e.Name == ".NET Blog");

// Change a property value
context.Entry(blog).Property(e => e.Name).CurrentValue = ".NET Blog (Updated!)";

// Add a new entity to the DbContext
context.Add(
    new Post
    {
        Blog = blog,
        Title = "What’s next for System.Text.Json?",
        Content = ".NET 5.0 was released recently and has come with many..."
    });

Console.WriteLine(context.ChangeTracker.DebugView.LongView);

In diesem Fall zeigt die Debugansicht für die Änderungs Nachverfolgung an, dass alle Entitäts Zustände und Eigenschafts Änderungen bekannt sind, auch wenn keine Änderungen vorgenommen wurden.In this case the change tracker debug view shows that all entity states and property modifications are known, even though detection of changes has not happened. Dies liegt daran PropertyEntry.CurrentValue , dass eine EF Core Methode ist, was bedeutet, dass EF Core sofort die von dieser Methode vorgenommene Änderung kennt.This is because PropertyEntry.CurrentValue is an EF Core method, which means that EF Core immediately knows about the change made by this method. Ebenso DbContext.Add ermöglicht das Aufrufen von EF Core, sofort über die neue Entität zu informieren und Sie entsprechend zu verfolgen.Likewise, calling DbContext.Add allows EF Core to immediately know about the new entity and track it appropriately.

Tipp

Versuchen Sie nicht, Änderungen zu erkennen, indem Sie immer EF Core-Methoden verwenden, um Entitäts Änderungen vorzunehmen.Don't attempt to avoid detecting changes by always using EF Core methods to make entity changes. Dies ist oft schwieriger und führt zu einer geringeren Leistung, als Änderungen an Entitäten auf normale Weise vorzunehmen.Doing so is often more cumbersome and performs less well than making changes to entities in the normal way. Das Ziel dieses Dokuments besteht darin, zu informieren, wann Änderungen erforderlich sind und wann dies nicht der Fall ist.The intention of this document is to inform as to when detecting changes is needed and when it is not. Die Absicht besteht nicht darin, die Vermeidung von Änderungs Erkennung zu fördern.The intention is not to encourage avoidance of change detection.

Methoden zum automatischen Erkennen von ÄnderungenMethods that automatically detect changes

DetectChanges() wird automatisch von Methoden aufgerufen, bei denen sich dies wahrscheinlich auf die Ergebnisse auswirkt.DetectChanges() is called automatically by methods where doing so is likely to impact the results. Diese Methoden werden im Anschluss beschrieben:These methods are:

Es gibt auch einige stellen, an denen die Ermittlung von Änderungen nur auf einer einzelnen Entitäts Instanz statt auf dem gesamten Diagramm der nach verfolgten Entitäten erfolgt.There are also some places where detection of changes happens on only a single entity instance, rather than on the entire graph of tracked entities. Diese Stellen sind:These places are:

  • Bei Verwendung DbContext.Entry von, um sicherzustellen, dass der Zustand der Entität und die geänderten Eigenschaften auf dem neuesten Stand sind.When using DbContext.Entry, to ensure that the entity's state and modified properties are up-to-date.
  • Wenn Sie EntityEntry Methoden wie Property , Collection oder verwenden Reference Member , um zu gewährleisten, dass Eigenschafts Änderungen, aktuelle Werte usw. auf dem neuesten Stand sind.When using EntityEntry methods such as Property, Collection, Reference or Member to ensure property modifications, current values, etc. are up-to-date.
  • Wenn eine abhängige/untergeordnete Entität gelöscht wird, weil eine erforderliche Beziehung getrennt wurde.When a dependent/child entity is going to be deleted because a required relationship has been severed. Dadurch wird erkannt, wenn eine Entität nicht gelöscht werden soll, weil Sie erneut übergeordnet ist.This detects when an entity should not be deleted because it has been re-parented.

Die lokale Erkennung von Änderungen für eine einzelne Entität kann explizit durch Aufrufen von ausgelöst werden EntityEntry.DetectChanges() .Local detection of changes for a single entity can be triggered explicitly by calling EntityEntry.DetectChanges().

Hinweis

Lokale Erkennungs Änderungen können einige Änderungen übersehen, die durch eine vollständige Erkennung gefunden werden.Local detect changes can miss some changes that a full detection would find. Dies geschieht, wenn kaskadierende Aktionen, die sich aus nicht erkannten Änderungen an anderen Entitäten ergeben, Auswirkungen auf die betreffende Entität haben.This happens when cascading actions resulting from undetected changes to other entities have an impact on the entity in question. In solchen Fällen muss die Anwendung möglicherweise eine vollständige Überprüfung aller Entitäten erzwingen, indem explizit aufgerufen wird ChangeTracker.DetectChanges() .In such situations the application may need to force a full scan of all entities by explicitly calling ChangeTracker.DetectChanges().

Deaktivieren der automatischen Änderungs ErkennungDisabling automatic change detection

Die Leistung beim Erkennen von Änderungen ist für die meisten Anwendungen kein Engpass.The performance of detecting changes is not a bottleneck for most applications. Das Erkennen von Änderungen kann jedoch zu einem Leistungsproblem für einige Anwendungen werden, die Tausende von Entitäten nachverfolgen.However, detecting changes can become a performance problem for some applications that track thousands of entities. (Die genaue Anzahl hängt von vielen Faktoren ab, z. b. von der Anzahl der Eigenschaften in der Entität.) Aus diesem Grund kann die automatische Erkennung von Änderungen mithilfe von deaktiviert werden ChangeTracker.AutoDetectChangesEnabled .(The exact number will dependent on many things, such as the number of properties in the entity.) For this reason the automatic detection of changes can be disabled using ChangeTracker.AutoDetectChangesEnabled. Sie sollten z. b. Verknüpfungs Entitäten in einer m:n-Beziehung mit Nutzlasten verarbeiten:For example, consider processing join entities in a many-to-many relationship with payloads:

public override int SaveChanges()
{
    foreach (var entityEntry in ChangeTracker.Entries<PostTag>()) // Detects changes automatically
    {
        if (entityEntry.State == EntityState.Added)
        {
            entityEntry.Entity.TaggedBy = "ajcvickers";
            entityEntry.Entity.TaggedOn = DateTime.Now;
        }
    }

    try
    {
        ChangeTracker.AutoDetectChangesEnabled = false;
        return base.SaveChanges(); // Avoid automatically detecting changes again here
    }
    finally
    {
        ChangeTracker.AutoDetectChangesEnabled = true;
    }
}

Wie wir im vorherigen Abschnitt wissen, erkennen sowohl als ChangeTracker.Entries<TEntity>() auch DbContext.SaveChanges automatisch Änderungen.As we know from the previous section, both ChangeTracker.Entries<TEntity>() and DbContext.SaveChanges automatically detect changes. Nach dem Aufrufen von Einträgen führt der Code jedoch keine Änderungen an Entitäts-oder Eigenschafts Zuständen aus.However, after calling Entries, the code does not then make any entity or property state changes. (Das Festlegen normaler Eigenschaftswerte für hinzugefügte Entitäten führt nicht zu Zustandsänderungen.) Der Code deaktiviert daher unnötige automatische Änderungs Erkennung beim Aufrufen der Basis-SaveChanges-Methode.(Setting normal property values on Added entities does not cause any state changes.) The code therefore disables unnecessary automatic change detection when calling down into the base SaveChanges method. Der Code verwendet auch einen try/after-Block, um sicherzustellen, dass die Standardeinstellung wieder hergestellt wird, auch wenn SaveChanges fehlschlägt.The code also makes use of a try/finally block to ensure that the default setting is restored even if SaveChanges fails.

Tipp

Gehen Sie nicht davon aus, dass der Code die automatische Änderungs Erkennung in deaktivieren muss, damit Sie gut funktioniert.Do not assume that your code must disable automatic change detection to to perform well. Dies ist nur erforderlich, wenn die Profilerstellung für eine Anwendung, bei der viele Entitäten nachverfolgt werden, ein Problem auftritt.This is only needed when profiling an application tracking many entities indicates that performance of change detection is an issue.

Erkennen von Änderungen und Wert KonvertierungenDetecting changes and value conversions

Um die Nachverfolgung von Momentaufnahmen mit einem Entitätstyp zu verwenden, muss EF Core in der Lage sein,To use snapshot change tracking with an entity type, EF Core must be able to:

  • Erstellen Sie eine Momentaufnahme jedes Eigenschafts Werts, wenn die Entität nachverfolgt wird.Make a snapshot of each property value when the entity is tracked
  • Vergleicht diesen Wert mit dem aktuellen Wert der Eigenschaft.Compare this value to the current value of the property
  • Generieren Sie einen Hashcode für den Wert.Generate a hash code for the value

Dies erfolgt automatisch durch EF Core für Typen, die direkt der Datenbank zugeordnet werden können.This is handled automatically by EF Core for types that can be directly mapped to the database. Wenn jedoch ein Wert Konverter zum Zuordnen einer Eigenschaft verwendet wird, muss dieser Konverter angeben, wie diese Aktionen durchgeführt werden sollen.However, when a value converter is used to map a property, then that converter must specify how to perform these actions. Dies wird mit einem Wert Vergleich erreicht und in der Dokumentation zu den Wert comparern ausführlich beschrieben.This is achieved with a value comparer, and is described in detail in the Value Comparers documentation.

Benachrichtigungs EntitätenNotification entities

Die Änderungs Nachverfolgung von Momentaufnahmen wird für die meisten Anwendungen empfohlen.Snapshot change tracking is recommended for most applications. Allerdings können Anwendungen, die viele Entitäten nachverfolgen und/oder viele Änderungen an diesen Entitäten vornehmen, von der Implementierung von Entitäten profitieren, die EF Core automatisch benachrichtigen, wenn sich ihre Eigenschaften und Navigations Werte ändernHowever, applications that track many entities and/or make many changes to those entities may benefit from implementing entities that automatically notify EF Core when their property and navigation values change. Diese werden als "Benachrichtigungs Entitäten" bezeichnet.These are known as "notification entities".

Implementieren von Benachrichtigungs EinheitenImplementing notification entities

Benachrichtigungs Entitäten verwenden die INotifyPropertyChanging -und- INotifyPropertyChanged Schnittstellen, die Teil der .net-Basisklassen Bibliothek (Base Class Library, BCL) sind.Notification entities make use of the INotifyPropertyChanging and INotifyPropertyChanged interfaces, which are part of the .NET base class library (BCL). Diese Schnittstellen definieren Ereignisse, die vor und nach dem Ändern eines Eigenschafts Werts ausgelöst werden müssen.These interfaces define events that must be fired before and after changing a property value. Beispiel:For example:

public class Blog : INotifyPropertyChanging, INotifyPropertyChanged
{
    public event PropertyChangingEventHandler PropertyChanging;
    public event PropertyChangedEventHandler PropertyChanged;

    private int _id;

    public int Id
    {
        get => _id;
        set
        {
            PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(nameof(Id)));
            _id = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Id)));
        }
    }

    private string _name;

    public string Name
    {
        get => _name;
        set
        {
            PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(nameof(Name)));
            _name = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
        }
    }

    public IList<Post> Posts { get; } = new ObservableCollection<Post>();
}

Darüber hinaus muss jede Auflistungs Navigation implementieren INotifyCollectionChanged . im obigen Beispiel wird dies mithilfe eines ObservableCollection<T> von Beiträgen erfüllt.In addition, any collection navigations must implement INotifyCollectionChanged; in the example above this satisfied by using an ObservableCollection<T> of posts. EF Core ist auch mit einer ObservableHashSet<T> Implementierung ausgeliefert, die auf Kosten einer stabilen Reihenfolge effizientere Suchvorgänge bietet.EF Core also ships with an ObservableHashSet<T> implementation that has more efficient lookups at the expense of stable ordering.

Der größte Teil dieses Benachrichtigungs Codes wird in der Regel in eine nicht zugeordnete Basisklasse verschoben.Most of this notification code is typically moved into an unmapped base class. Beispiel:For example:

public class Blog : NotifyingEntity
{
    private int _id;

    public int Id
    {
        get => _id;
        set => SetWithNotify(value, out _id);
    }

    private string _name;

    public string Name
    {
        get => _name;
        set => SetWithNotify(value, out _name);
    }

    public IList<Post> Posts { get; } = new ObservableCollection<Post>();
}

public abstract class NotifyingEntity : INotifyPropertyChanging, INotifyPropertyChanged
{
    protected void SetWithNotify<T>(T value, out T field, [CallerMemberName] string propertyName = "")
    {
        NotifyChanging(propertyName);
        field = value;
        NotifyChanged(propertyName);
    }

    public event PropertyChangingEventHandler PropertyChanging;
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyChanged(string propertyName)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    private void NotifyChanging(string propertyName)
        => PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));
}

Benachrichtigungs Entitäten konfigurierenConfiguring notification entities

Es gibt keine Möglichkeit, EF Core zu überprüfen, ob INotifyPropertyChanging oder INotifyPropertyChanged vollständig für die Verwendung mit EF Core implementiert sind.There is no way for EF Core to validate that INotifyPropertyChanging or INotifyPropertyChanged are fully implemented for use with EF Core. Insbesondere verwenden einige Verwendungsmöglichkeiten dieser Schnittstellen dies nur für bestimmte Eigenschaften, nicht für alle Eigenschaften (einschließlich Navigationen), wie dies für EF Core erforderlich ist.In particular, some uses of these interfaces do so with notifications only on certain properties, rather than on all properties (including navigations) as required by EF Core. Aus diesem Grund wird EF Core nicht automatisch in diese Ereignisse eingebunden.For this reason, EF Core does not automatically hook into these events.

Stattdessen müssen EF Core so konfiguriert werden, dass diese Benachrichtigungs Entitäten verwendet werden.Instead, EF Core must be configured to use these notification entities. Dies erfolgt in der Regel für alle Entitäts Typen durch Aufrufen von ModelBuilder.HasChangeTrackingStrategy .This is usually done for all entity types by calling ModelBuilder.HasChangeTrackingStrategy. Beispiel:For example:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangingAndChangedNotifications);
}

(Die Strategie kann auch unterschiedlich für verschiedene Entitäts Typen festgelegt werden EntityTypeBuilder.HasChangeTrackingStrategy . Dies ist jedoch in der Regel kontraproduktiv, da DetectChanges für die Typen, die keine Benachrichtigungs Entitäten sind, weiterhin erforderlich ist.)(The strategy can also be set differently for different entity types using EntityTypeBuilder.HasChangeTrackingStrategy, but this is usually counterproductive since DetectChanges is still required for those types that are not notification entities.)

Bei der vollständigen Benachrichtigungs Änderungs Nachverfolgung müssen sowohl INotifyPropertyChanging als auch INotifyPropertyChanged implementiert werden.Full notification change tracking requires that both INotifyPropertyChanging and INotifyPropertyChanged are implemented. Dies ermöglicht die Speicherung ursprünglicher Werte, kurz bevor der Eigenschafts Wert geändert wird, sodass EF Core keine Momentaufnahme erstellen muss, wenn die Entität nachverfolgt wird.This allows original values to be saved just before the property value is changed, avoiding the need for EF Core to create a snapshot when tracking the entity. Entitäts Typen, die nur implementieren, INotifyPropertyChanged können auch mit EF Core verwendet werden.Entity types that implement only INotifyPropertyChanged can also be used with EF Core. In diesem Fall erstellt EF immer noch eine Momentaufnahme, wenn eine Entität nachverfolgt wird, um die ursprünglichen Werte nachzuverfolgen. die Benachrichtigungen werden dann jedoch verwendet, um Änderungen sofort zu erkennen, anstatt dass DetectChanges aufgerufen werden müssen.In this case, EF still creates a snapshot when tracking an entity to keep track of original values, but then uses the notifications to detect changes immediately, rather than needing DetectChanges to be called.

Die unterschiedlichen ChangeTrackingStrategy Werte werden in der folgenden Tabelle zusammengefasst.The different ChangeTrackingStrategy values are summarized in the the following table.

ChangetrackingstrategyChangeTrackingStrategy Benötigte SchnittstellenInterfaces needed DetectChanges erforderlichNeeds DetectChanges Momentaufnahmen ursprünglicher WerteSnapshots original values
MomentaufnahmeSnapshot KeineNone JaYes JaYes
ChangedbenachrichtigungenChangedNotifications INotifyPropertyChangedINotifyPropertyChanged NeinNo JaYes
ChangingandchangedbenachrichtigungenChangingAndChangedNotifications INotifyPropertyChanged und INotifyPropertyChangingINotifyPropertyChanged and INotifyPropertyChanging NeinNo NeinNo
ChangingandchangednotificationswithoriginalvaluesChangingAndChangedNotificationsWithOriginalValues INotifyPropertyChanged und INotifyPropertyChangingINotifyPropertyChanged and INotifyPropertyChanging NeinNo JaYes

Mit Benachrichtigungs EntitätenUsing notification entities

Benachrichtigungs Entitäten Verhalten sich wie alle anderen Entitäten, mit dem Unterschied, dass das vornehmen von Änderungen an den Entitäts Instanzen keinen ChangeTracker.DetectChanges() Rückruf von erfordertNotification entities behave like any other entities, except that making changes to the entity instances do not require a call to ChangeTracker.DetectChanges() to detect these changes. Beispiel:For example:

using var context = new BlogsContext();
var blog = context.Blogs.Include(e => e.Posts).First(e => e.Name == ".NET Blog");

// Change a property value
blog.Name = ".NET Blog (Updated!)";

// Add a new entity to a navigation
blog.Posts.Add(
    new Post
    {
        Title = "What’s next for System.Text.Json?", Content = ".NET 5.0 was released recently and has come with many..."
    });

Console.WriteLine(context.ChangeTracker.DebugView.LongView);

Bei normalen Entitäten zeigte die Debugansicht der Änderungs nach Verfolgung, dass diese Änderungen erst erkannt wurden, wenn DetectChanges aufgerufen wurde.With normal entities, the change tracker debug view showed that these changes were not detected until DetectChanges was called. Wenn Sie die Debugansicht anzeigen, wenn Benachrichtigungs Entitäten verwendet werden, zeigt dies, dass diese Änderungen sofort erkannt wurden:Looking at the debug view when notification entities are used shows that these changes have been detected immediately:

Blog {Id: 1} Modified
  Id: 1 PK
  Name: '.NET Blog (Updated!)' Modified
  Posts: [{Id: 1}, {Id: 2}, {Id: -2147482643}]
Post {Id: -2147482643} Added
  Id: -2147482643 PK Temporary
  BlogId: 1 FK
  Content: '.NET 5.0 was released recently and has come with many...'
  Title: 'What's next for System.Text.Json?'
  Blog: {Id: 1}
Post {Id: 1} Unchanged
  Id: 1 PK
  BlogId: 1 FK
  Content: 'Announcing the release of EF Core 5.0, a full featured cross...'
  Title: 'Announcing the Release of EF Core 5.0'
  Blog: {Id: 1}
Post {Id: 2} Unchanged
  Id: 2 PK
  BlogId: 1 FK
  Content: 'F# 5 is the latest version of F#, the functional programming...'
  Title: 'Announcing F# 5'
  Blog: {Id: 1}

Proxys zur ÄnderungsnachverfolgungChange-tracking proxies

Hinweis

Proxys für die Änderungs Nachverfolgung wurden in EF Core 5,0 eingeführt.Change-tracking proxies were introduced in EF Core 5.0.

EF Core können Proxy Typen, die und implementieren, dynamisch generieren INotifyPropertyChanging INotifyPropertyChanged .EF Core can dynamically generate proxy types that implement INotifyPropertyChanging and INotifyPropertyChanged. Hierfür müssen Sie das nuget-Paket Microsoft. entityframeworkcore. Proxies installieren und Proxys für die Änderungs Nachverfolgung wie folgt aktivieren UseChangeTrackingProxies :This requires installing the Microsoft.EntityFrameworkCore.Proxies NuGet package, and enabling change-tracking proxies with UseChangeTrackingProxies For example:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.UseChangeTrackingProxies();

Das Erstellen eines dynamischen Proxys umfasst das Erstellen eines neuen dynamischen .net-Typs (mit der Implementierung von " Castle. Core Proxies"), der vom Entitätstyp erbt und dann alle Eigenschaften Setter überschreibt.Creating a dynamic proxy involves creating a new, dynamic .NET type (using the Castle.Core proxies implementation), which inherits from the entity type and then overrides all property setters. Entitäts Typen für Proxys müssen daher Typen sein, die von geerbt werden können und über Eigenschaften verfügen müssen, die überschrieben werden können.Entity types for proxies must therefore be types that can be inherited from and must have properties that can be overridden. Außerdem müssen die explizit erstellten Sammlungs Navigation Beispiels INotifyCollectionChanged Weise Folgendes implementieren:Also, collection navigations created explicitly must implement INotifyCollectionChanged For example:

public class Blog
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }

    public virtual IList<Post> Posts { get; } = new ObservableCollection<Post>();
}

public class Post
{
    public virtual int Id { get; set; }
    public virtual string Title { get; set; }
    public virtual string Content { get; set; }

    public virtual int BlogId { get; set; }
    public virtual Blog Blog { get; set; }
}

Ein wesentlicher Nachteil von Proxys für die Änderungs Nachverfolgung besteht darin, dass EF Core immer Instanzen des Proxys nachverfolgen muss, niemals Instanzen des zugrunde liegenden Entitäts Typs.One significant downside to change-tracking proxies is that EF Core must always track instances of the proxy, never instances of the underlying entity type. Dies liegt daran, dass Instanzen des zugrunde liegenden Entitäts Typs keine Benachrichtigungen generieren, was bedeutet, dass an diesen Entitäten vorgenommene Änderungen übersehen werden.This is because instances of the underlying entity type will not generate notifications, which means changes made to these entities will be missed.

EF Core beim Abfragen der Datenbank automatisch Proxy Instanzen erstellt, ist dieser Nachteil in der Regel auf das Nachverfolgen neuer Entitäts Instanzen beschränkt.EF Core creates proxy instances automatically when querying the database, so this downside is generally limited to tracking new entity instances. Diese Instanzen müssen mithilfe der CreateProxy Erweiterungs Methoden und nicht auf die normale Weise mithilfe von erstellt werden new .These instances must be created using the CreateProxy extension methods, and not in the normal way using new. Dies bedeutet, dass der Code aus den vorherigen Beispielen nun Folgendes verwenden muss CreateProxy :This means the code from the previous examples must now make use of CreateProxy:

using var context = new BlogsContext();
var blog = context.Blogs.Include(e => e.Posts).First(e => e.Name == ".NET Blog");

// Change a property value
blog.Name = ".NET Blog (Updated!)";

// Add a new entity to a navigation
blog.Posts.Add(
    context.CreateProxy<Post>(
        p =>
        {
            p.Title = "What’s next for System.Text.Json?";
            p.Content = ".NET 5.0 was released recently and has come with many...";
        }));

Console.WriteLine(context.ChangeTracker.DebugView.LongView);

Änderungs nach Verfolgungs EreignisseChange tracking events

EF Core löst das- ChangeTracker.Tracked Ereignis aus, wenn eine Entität zum ersten Mal nachverfolgt wird.EF Core fires the ChangeTracker.Tracked event when an entity is tracked for the first time. Zukünftige Entitäts Zustandsänderungen führen zu ChangeTracker.StateChanged Ereignissen.Future entity state changes result in ChangeTracker.StateChanged events. Weitere Informationen finden Sie unter .NET-Ereignisse in EF Core.See .NET Events in EF Core for more information.

Hinweis

Das- StateChanged Ereignis wird nicht ausgelöst, wenn eine Entität zum ersten Mal nachverfolgt wird, auch wenn sich der Status von Detached in einen der anderen Zustände geändert hat.The StateChanged event is not fired when an entity is first tracked, even though the state has changed from Detached to one of the other states. Achten Sie darauf, sowohl auf StateChanged -als auch auf Tracked Ereignisse zu lauschen, um alle relevanten Benachrichtigungen zu erhaltenMake sure to listen for both StateChanged and Tracked events to get all relevant notifications.