Události .NET v EF Core
Tip
Ukázku událostí si můžete stáhnout z GitHubu.
Entity Framework Core (EF Core) zveřejňuje události .NET, které budou fungovat jako zpětná volání, když v kódu EF Core dojde k určitým věcem. Události jsou jednodušší než průsečíky a umožňují flexibilnější registraci. Jsou ale jenom synchronní, takže nemohou provádět neblokující asynchronní I/O.
Události se registrují na DbContext
instanci. Pomocí diagnostického naslouchacího procesu můžete získat stejné informace, ale pro všechny instance DbContextu v rámci tohoto procesu.
Události vyvolané EF Core
EF Core vyvolává následující události:
Událost | Při vyvolání |
---|---|
DbContext.SavingChanges | Na začátku SaveChanges nebo SaveChangesAsync |
DbContext.SavedChanges | Na konci úspěšného SaveChanges nebo SaveChangesAsync |
DbContext.SaveChangesFailed | Na konci neúspěšného nebo neúspěšného SaveChangesSaveChangesAsync |
ChangeTracker.Tracked | Když je entita sledována kontextem |
ChangeTracker.StateChanged | Při změně stavu sledované entity |
Příklad: Změny stavu časového razítka
Každá entita, kterou sleduje DbContext, má .EntityState Například stav označuje, Added
že entita bude vložena do databáze.
V tomto příkladu se Tracked pomocí událostí StateChanged zjistí, kdy entita změní stav. Potom entitu označí aktuálním časem označujícím, kdy k této změně došlo. Výsledkem jsou časové razítka označující, kdy byla entita vložena, odstraněna nebo naposledy aktualizována.
Typy entit v tomto příkladu implementují rozhraní, které definuje vlastnosti časového razítka:
public interface IHasTimestamps
{
DateTime? Added { get; set; }
DateTime? Deleted { get; set; }
DateTime? Modified { get; set; }
}
Metoda v DbContext aplikace pak může nastavit časové razítka pro libovolnou entitu, která implementuje toto rozhraní:
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;
}
}
}
Tato metoda má odpovídající podpis, který se má použít jako obslužná rutina události jak pro události, tak Tracked
StateChanged
pro události. Obslužná rutina je registrována pro obě události v konstruktoru DbContext. Mějte na paměti, že události lze kdykoli připojit k DbContext; to není nutné, aby k tomu došlo v kontextovém konstruktoru.
public BlogsContext()
{
ChangeTracker.StateChanged += UpdateTimestamps;
ChangeTracker.Tracked += UpdateTimestamps;
}
Obě události jsou potřeba, protože nové entity se aktivují Tracked
při prvním sledování událostí. StateChanged
Události se aktivují pouze u entit, které mění stav, zatímco jsou již sledovány.
Ukázka pro tento příklad obsahuje jednoduchou konzolovou aplikaci, která provádí změny v databázi blogování:
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();
}
Výstup z tohoto kódu ukazuje změny stavu a použité časové razítko:
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