.Net-Ereignisse in EF Core.NET Events in EF Core

Tipp

Sie können das Ereignis Beispiel von GitHub herunterladen.You can download the events sample from GitHub.

Entity Framework Core (EF Core) macht .net-Ereignisse verfügbar, die als Rückrufe fungieren, wenn bestimmte Dinge im EF Core Code auftreten.Entity Framework Core (EF Core) exposes .NET events to act as callbacks when certain things happen in the EF Core code. Ereignisse sind einfacher als Interceptors und ermöglichen eine flexiblere Registrierung.Events are simpler than interceptors and allow more flexible registration. Sie sind jedoch nur synchron und können daher keine nicht blockierenden asynchronen E/A-Vorgänge durchführen.However, they are sync only and so cannot perform non-blocking async I/O.

Ereignisse werden pro DbContext Instanz registriert.Events are registered per DbContext instance. Verwenden Sie einen Diagnoselistener, um dieselben Informationen abzurufen, jedoch für alle DbContext-Instanzen im Prozess.Use a diagnostic listener to get the same information but for all DbContext instances in the process.

Ereignisse, die von EF Core ausgelöst werdenEvents raised by EF Core

Die folgenden Ereignisse werden von EF Core ausgelöst:The following events are raised by EF Core:

EreignisEvent Eingeführt in VersionVersion introduced Wenn ausgelöstWhen raised
DbContext.SavingChanges 5.05.0 Am Anfang von SaveChanges oder SaveChangesAsyncAt the start of SaveChanges or SaveChangesAsync
DbContext.SavedChanges 5.05.0 Am Ende eines erfolgreichen SaveChanges oder SaveChangesAsyncAt the end of a successful SaveChanges or SaveChangesAsync
DbContext.SaveChangesFailed 5.05.0 Am Ende einer fehlgeschlagenen SaveChanges oder SaveChangesAsyncAt the end of a failed SaveChanges or SaveChangesAsync
ChangeTracker.Tracked 2.12.1 Wenn eine Entität vom Kontext nachverfolgt wirdWhen an entity is tracked by the context
ChangeTracker.StateChanged 2.12.1 Wenn eine nach verfolgte Entität ihren Zustand ändertWhen a tracked entity changes its state

Beispiel: Timestamp-ZustandsänderungenExample: Timestamp state changes

Jede Entität, die von einem dbcontext nachverfolgt wird, hat eine EntityStateEach entity tracked by a DbContext has an EntityState. Der-Status gibt beispielsweise an Added , dass die Entität in die Datenbank eingefügt wird.For example, the Added state indicates that the entity will be inserted into the database.

In diesem Beispiel werden das Tracked -Ereignis und das- StateChanged Ereignis verwendet, um zu erkennen, wann sich einThis example uses the Tracked and StateChanged events to detect when an entity changes state. Anschließend wird die Entität mit der aktuellen Zeitstempel versehen, die anzeigt, wann diese Änderung eingetreten ist.It then stamps the entity with the current time indicating when this change happened. Dies führt zu Zeitstempel, die angeben, wann die Entität eingefügt, gelöscht und/oder zuletzt aktualisiert wurde.This results in timestamps indicating when the entity was inserted, deleted, and/or last updated.

Die Entitäts Typen in diesem Beispiel implementieren eine Schnittstelle, die die Zeitstempel-Eigenschaften definiert:The entity types in this example implement an interface that defines the timestamp properties:

public interface IHasTimestamps
{
    DateTime? Added { get; set; }
    DateTime? Deleted { get; set; }
    DateTime? Modified { get; set; }
}

Eine Methode im dbcontext der Anwendung kann dann Zeitstempel für jede Entität festlegen, die diese Schnittstelle implementiert:A method on the application's DbContext can then set timestamps for any entity that implements this interface:

private static void UpdateTimestamps(object sender, EntityEntryEventArgs e)
{
    if (e.Entry.Entity is IHasTimestamps entityWithTimestamps)
    {
        switch (e.Entry.State)
        {
            case EntityState.Deleted:
                entityWithTimestamps.Deleted = DateTime.UtcNow;
                Console.WriteLine($"Stamped for delete: {e.Entry.Entity}");
                break;
            case EntityState.Modified:
                entityWithTimestamps.Modified = DateTime.UtcNow;
                Console.WriteLine($"Stamped for update: {e.Entry.Entity}");
                break;
            case EntityState.Added:
                entityWithTimestamps.Added = DateTime.UtcNow;
                Console.WriteLine($"Stamped for insert: {e.Entry.Entity}");
                break;
        }
    }
}

Diese Methode verfügt über die entsprechende Signatur, die als Ereignishandler für das-Ereignis und das-Ereignis verwendet werden soll Tracked StateChanged .This method has the appropriate signature to use as an event handler for both the Tracked and StateChanged events. Der Handler ist für beide Ereignisse im dbcontext-Konstruktor registriert.The handler is registered for both events in the DbContext constructor. Beachten Sie, dass Ereignisse jederzeit an einen dbcontext angefügt werden können. Es ist nicht erforderlich, dass dies im kontextkonstruktor auftritt.Note that events can be attached to a DbContext at any time; it is not required that this happen in the context constructor.

public BlogsContext()
{
    ChangeTracker.StateChanged += UpdateTimestamps;
    ChangeTracker.Tracked += UpdateTimestamps;
}

Beide Ereignisse sind erforderlich, da neue Entitäten Ereignisse auslösen, Tracked Wenn Sie zum ersten Mal nachverfolgt werden.Both events are needed because new entities fire Tracked events when they are first tracked. StateChanged Ereignisse werden nur für Entitäten ausgelöst, die den Zustand ändern, während Sie bereits nachverfolgt werden.StateChanged events are only fired for entities that change state while they are already being tracked.

Das Beispiel für dieses Beispiel enthält eine einfache Konsolenanwendung, die Änderungen an der Blog Datenbank vornimmt:The sample for this example contains a simple console application that makes changes to the blogging database:

using (var context = new BlogsContext())
{
    context.Database.EnsureDeleted();
    context.Database.EnsureCreated();

    context.Add(
        new Blog
        {
            Id = 1,
            Name = "EF Blog",
            Posts = { new Post { Id = 1, Title = "EF Core 3.1!" }, new Post { Id = 2, Title = "EF Core 5.0!" } }
        });

    context.SaveChanges();
}

using (var context = new BlogsContext())
{
    var blog = context.Blogs.Include(e => e.Posts).Single();

    blog.Name = "EF Core Blog";
    context.Remove(blog.Posts.First());
    blog.Posts.Add(new Post { Id = 3, Title = "EF Core 6.0!" });

    context.SaveChanges();
}

Die Ausgabe dieses Codes zeigt die Zustandsänderungen und die angewendeten Zeitstempel:The output from this code shows the state changes happening and the timestamps being applied:

Stamped for insert: Blog 1 Added on: 10/15/2020 11:01:26 PM
Stamped for insert: Post 1 Added on: 10/15/2020 11:01:26 PM
Stamped for insert: Post 2 Added on: 10/15/2020 11:01:26 PM
Stamped for delete: Post 1 Added on: 10/15/2020 11:01:26 PM Deleted on: 10/15/2020 11:01:26 PM
Stamped for update: Blog 1 Added on: 10/15/2020 11:01:26 PM Modified on: 10/15/2020 11:01:26 PM
Stamped for insert: Post 3 Added on: 10/15/2020 11:01:26 PM