Zdarzenia platformy .NET w programie EF Core
Napiwek
Przykładowe zdarzenia można pobrać z usługi GitHub.
Program Entity Framework Core (EF Core) uwidacznia zdarzenia platformy .NET do działania jako wywołania zwrotnego, gdy w kodzie platformy EF Core występują pewne elementy. Zdarzenia są prostsze niż przechwytuje i umożliwiają bardziej elastyczną rejestrację. Jednak są one tylko do synchronizacji, dlatego nie mogą wykonywać nieblokujących asynchronicznych operacji we/wy.
Zdarzenia są rejestrowane na DbContext
wystąpienie. Użyj odbiornika diagnostycznego, aby uzyskać te same informacje ale dla wszystkich wystąpień obiektu DbContext w procesie.
Zdarzenia zgłaszane przez program EF Core
Następujące zdarzenia są wywoływane przez program EF Core:
Wydarzenie | Po podniesioniu |
---|---|
DbContext.SavingChanges | Na początku SaveChanges lub SaveChangesAsync |
DbContext.SavedChanges | Na końcu powodzenia SaveChanges lub SaveChangesAsync |
DbContext.SaveChangesFailed | Na końcu błędu SaveChanges lub SaveChangesAsync |
ChangeTracker.Tracked | Kiedy jednostka jest śledzona przez kontekst |
ChangeTracker.StateChanged | Gdy śledzona jednostka zmienia swój stan |
Przykład: zmiany stanu znacznika czasu
Każda jednostka śledzona przez element DbContext ma element EntityState. Na przykład stan wskazuje, Added
że jednostka zostanie wstawiona do bazy danych.
W tym przykładzie użyto zdarzeń Tracked i StateChanged do wykrywania, kiedy jednostka zmienia stan. Następnie oznacza jednostkę bieżącą godziną wskazującą, kiedy ta zmiana się wydarzyła. Spowoduje to znaczniki czasu wskazujące, kiedy jednostka została wstawiona, usunięta i/lub ostatnia aktualizacja.
Typy jednostek w tym przykładzie implementują interfejs definiujący właściwości znacznika czasu:
public interface IHasTimestamps
{
DateTime? Added { get; set; }
DateTime? Deleted { get; set; }
DateTime? Modified { get; set; }
}
Metoda w obiekcie DbContext aplikacji może następnie ustawić znaczniki czasu dla dowolnej jednostki, która implementuje ten interfejs:
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;
}
}
}
Ta metoda ma odpowiedni podpis do użycia jako program obsługi zdarzeń zarówno dla zdarzeń, jak Tracked
i StateChanged
. Program obsługi jest rejestrowany dla obu zdarzeń w konstruktorze DbContext. Należy pamiętać, że zdarzenia mogą być dołączane do obiektu DbContext w dowolnym momencie; nie jest wymagane, aby miało to miejsce w konstruktorze kontekstu.
public BlogsContext()
{
ChangeTracker.StateChanged += UpdateTimestamps;
ChangeTracker.Tracked += UpdateTimestamps;
}
Oba zdarzenia są potrzebne, ponieważ nowe jednostki uruchamiają Tracked
zdarzenia po pierwszym śledzeniu. StateChanged
Zdarzenia są wyzwalane tylko dla jednostek, które zmieniają stan, gdy są już śledzone.
Przykład dla tego przykładu zawiera prostą aplikację konsolową, która wprowadza zmiany w bazie danych blogów:
using (var context = new BlogsContext())
{
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
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!" } }
});
await context.SaveChangesAsync();
}
using (var context = new BlogsContext())
{
var blog = await context.Blogs.Include(e => e.Posts).SingleAsync();
blog.Name = "EF Core Blog";
context.Remove(blog.Posts.First());
blog.Posts.Add(new Post { Id = 3, Title = "EF Core 6.0!" });
await context.SaveChangesAsync();
}
Dane wyjściowe z tego kodu pokazują zmiany stanu i zastosowane znaczniki czasu:
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