Bagikan melalui


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())
{
    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();
}

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