Peristiwa .NET di EF Core
Tip
Anda dapat mengunduh sampel peristiwa dari GitHub.
Entity Framework Core (EF Core) mengekspos peristiwa .NET untuk bertindak sebagai panggilan balik ketika hal-hal tertentu terjadi dalam kode EF Core. Peristiwa lebih sederhana daripada pencegat dan memungkinkan pendaftaran yang lebih fleksibel. Namun, mereka hanya disinkronkan sehingga tidak bisa melakukan I/O asinkron non-pemblokiran.
Peristiwa didaftarkan per DbContext
instans. Menggunakan pendengar diagnostik untuk mendapatkan informasi yang sama, namun untuk seluruh instans DbContext dalam prosesnya.
Peristiwa yang diangkat oleh EF Core
Peristiwa berikut dimunculkan oleh EF Core:
Event | Ketika dinaikkan |
---|---|
DbContext.SavingChanges | Pada awal SaveChanges atau SaveChangesAsync |
DbContext.SavedChanges | Di akhir keberhasilan SaveChanges atau SaveChangesAsync |
DbContext.SaveChangesFailed | Di akhir gagal SaveChanges atau SaveChangesAsync |
ChangeTracker.Tracked | Saat entitas dilacak oleh konteks |
ChangeTracker.StateChanged | Saat entitas terlacak mengubah statusnya |
Contoh: Perubahan status tanda waktu
Setiap entitas yang dilacak oleh DbContext memiliki EntityState. Misalnya, status Added
menunjukkan bahwa entitas akan dimasukkan ke dalam database.
Contoh ini menggunakan Tracked peristiwa dan StateChanged untuk mendeteksi kapan entitas berubah status. Kemudian memberi stempel entitas dengan waktu saat ini yang menunjukkan kapan perubahan ini terjadi. Ini menghasilkan tanda waktu yang menunjukkan kapan entitas dimasukkan, dihapus, dan/atau terakhir diperbarui.
Jenis entitas dalam contoh ini mengimplementasikan antarmuka yang menentukan properti tanda waktu:
public interface IHasTimestamps
{
DateTime? Added { get; set; }
DateTime? Deleted { get; set; }
DateTime? Modified { get; set; }
}
Metode pada DbContext aplikasi kemudian dapat mengatur tanda waktu untuk entitas apa pun yang mengimplementasikan antarmuka ini:
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;
}
}
}
Metode ini memiliki tanda tangan yang sesuai untuk digunakan sebagai penanganan aktivitas untuk Tracked
peristiwa dan StateChanged
. Handler terdaftar untuk kedua peristiwa di konstruktor DbContext. Perhatikan bahwa peristiwa dapat dilampirkan ke DbContext kapan saja; tidak diperlukan bahwa ini terjadi dalam konstruktor konteks.
public BlogsContext()
{
ChangeTracker.StateChanged += UpdateTimestamps;
ChangeTracker.Tracked += UpdateTimestamps;
}
Kedua peristiwa diperlukan karena entitas baru menembak Tracked
peristiwa ketika pertama kali dilacak. StateChanged
peristiwa hanya diaktifkan untuk entitas yang mengubah status saat sudah dilacak.
Sampel untuk contoh ini berisi aplikasi konsol sederhana yang membuat perubahan pada database blogging:
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();
}
Output dari kode ini menunjukkan perubahan status yang terjadi dan tanda waktu yang diterapkan:
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