EF Core 中的 .NET 事件
提示
您可以從 GitHub 下載事件範例 。
Entity Framework Core (EF Core) 會在 EF Core 程式碼中發生某些情況時,公開 .NET 事件 作為回呼。 事件比 攔截器 簡單,而且允許更有彈性的註冊。 不過,它們只是同步處理,因此無法執行非封鎖非同步 I/O。
每個 DbContext
實例都會註冊事件。 使用診斷接聽程式來取得相同的資訊,但是是針對處理序中的所有 DbCoNtext 執行個體。
EF Core 所引發的事件
EF Core 會引發下列事件:
Event | 引發時 |
---|---|
DbContext.SavingChanges | 或 的 SaveChanges 開頭 SaveChangesAsync |
DbContext.SavedChanges | 成功 SaveChanges 或結尾 SaveChangesAsync |
DbContext.SaveChangesFailed | 在失敗 SaveChanges 或結束時 SaveChangesAsync |
ChangeTracker.Tracked | 內容追蹤實體時 |
ChangeTracker.StateChanged | 當追蹤實體變更其狀態時 |
範例:時間戳記狀態變更
DbCoNtext 追蹤的每個實體都有 EntityState 。 例如, Added
狀態表示實體會插入資料庫中。
這個範例會使用 Tracked 和 StateChanged 事件來偵測實體何時變更狀態。 然後,它會加上實體的戳記,並加上目前時間,指出此變更發生的時間。 這會產生時間戳記,指出實體何時插入、刪除和/或上次更新。
此範例中的實體類型會實作定義時間戳記屬性的介面:
public interface IHasTimestamps
{
DateTime? Added { get; set; }
DateTime? Deleted { get; set; }
DateTime? Modified { get; set; }
}
接著,應用程式 DbCoNtext 上的方法可以設定任何實作此介面之實體的時間戳記:
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;
}
}
}
這個方法具有適當的簽章,可用來作為 和 StateChanged
事件的事件處理常式 Tracked
。 處理常式會在 DbCoNtext 建構函式中註冊這兩個事件。 請注意,事件可以隨時附加至 DbCoNtext;這不需要在內容建構函式中發生。
public BlogsContext()
{
ChangeTracker.StateChanged += UpdateTimestamps;
ChangeTracker.Tracked += UpdateTimestamps;
}
這兩個事件都是必要的,因為新實體會在第一次追蹤事件時引發 Tracked
事件。 StateChanged
事件只會針對在追蹤時 變更狀態的實體引發。
此範例的範例 包含對部落格資料庫進行變更的簡單主控台應用程式:
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();
}
此程式碼的輸出會顯示狀態變更,以及所套用的時間戳記:
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