昨天早上看到以前關注的一個 efcore 的 issue 被 closed ,因而看了一眼, ef core 新合併了一個 PR,在 DbContext
中增長了 SaveChanges
相關的幾個事件,具體的變動能夠參數 PR https://github.com/dotnet/efcore/pull/21862html
以前寫過兩篇關於 EF Core 作自動審計的文章git
第一次的實現須要顯式繼承一個 AuditDbContext
,在有些須要沒辦法修改 DbContext
或者原有 DbContext
已經有繼承某一個類,就沒有辦法用了,能夠參考 https://www.cnblogs.com/weihanli/p/auto-audit-for-entity-framework.htmlgithub
後面結合 AOP 改進了一版,經過一個審計切面邏輯完成自動審計,可是須要引入 AOP 組件支持,對於不想引入額外組件的項目來講也並不是特別友好,能夠參考 http://www.javashuo.com/article/p-hlleaiyr-nn.html數據庫
在這個 PR 合併以後,咱們能夠經過 SavingChanges
事件獲取保存以前 DbContext
的狀態,經過 SavedChanges
事件來獲取保存成功後的 DbContext
信息,SaveChangesFailed
事件獲取保存失敗信息ui
事件定義以下:.net
/// <summary> /// An event fired at the beginning of a call to <see cref="M:SaveChanges"/> or <see cref="M:SaveChangesAsync"/> /// </summary> public event EventHandler<SavingChangesEventArgs> SavingChanges; /// <summary> /// An event fired at the end of a call to <see cref="M:SaveChanges"/> or <see cref="M:SaveChangesAsync"/> /// </summary> public event EventHandler<SavedChangesEventArgs> SavedChanges; /// <summary> /// An event fired if a call to <see cref="M:SaveChanges"/> or <see cref="M:SaveChangesAsync"/> fails with an exception. /// </summary> public event EventHandler<SaveChangesFailedEventArgs> SaveChangesFailed;
事件參數定義以下:code
/// <summary> /// Base event arguments for the <see cref="M:DbContext.SaveChanges" /> and <see cref="M:DbContext.SaveChangesAsync" /> events. /// </summary> public abstract class SaveChangesEventArgs : EventArgs { /// <summary> /// Creates a base event arguments instance for <see cref="M:DbContext.SaveChanges" /> /// or <see cref="M:DbContext.SaveChangesAsync" /> events. /// </summary> /// <param name="acceptAllChangesOnSuccess"> The value passed to SaveChanges. </param> protected SaveChangesEventArgs(bool acceptAllChangesOnSuccess) { AcceptAllChangesOnSuccess = acceptAllChangesOnSuccess; } /// <summary> /// The value passed to <see cref="M:DbContext.SaveChanges" /> or <see cref="M:DbContext.SaveChangesAsync" />. /// </summary> public virtual bool AcceptAllChangesOnSuccess { get; } } /// <summary> /// Event arguments for the <see cref="DbContext.SavingChanges" /> event. /// </summary> public class SavingChangesEventArgs : SaveChangesEventArgs { /// <summary> /// Creates event arguments for the <see cref="M:DbContext.SavingChanges" /> event. /// </summary> /// <param name="acceptAllChangesOnSuccess"> The value passed to SaveChanges. </param> public SavingChangesEventArgs(bool acceptAllChangesOnSuccess) : base(acceptAllChangesOnSuccess) { } } /// <summary> /// Event arguments for the <see cref="DbContext.SavedChanges" /> event. /// </summary> public class SavedChangesEventArgs : SaveChangesEventArgs { /// <summary> /// Creates a new <see cref="SavedChangesEventArgs" /> instance with the given number of entities saved. /// </summary> /// <param name="acceptAllChangesOnSuccess"> The value passed to SaveChanges. </param> /// <param name="entitiesSavedCount"> The number of entities saved. </param> public SavedChangesEventArgs(bool acceptAllChangesOnSuccess, int entitiesSavedCount) : base(acceptAllChangesOnSuccess) { EntitiesSavedCount = entitiesSavedCount; } /// <summary> /// The number of entities saved. /// </summary> public virtual int EntitiesSavedCount { get; } } /// <summary> /// Event arguments for the <see cref="DbContext.SaveChangesFailed" /> event. /// </summary> public class SaveChangesFailedEventArgs : SaveChangesEventArgs { /// <summary> /// Creates a new <see cref="SaveChangesFailedEventArgs"/> instance with the exception that was thrown. /// </summary> /// <param name="acceptAllChangesOnSuccess"> The value passed to SaveChanges. </param> /// <param name="exception"> The exception thrown. </param> public SaveChangesFailedEventArgs(bool acceptAllChangesOnSuccess, [NotNull] Exception exception) : base(acceptAllChangesOnSuccess) { Exception = exception; } /// <summary> /// The exception thrown during<see cref="M:DbContext.SaveChanges"/> or <see cref="M:DbContext.SaveChangesAsync"/>. /// </summary> public virtual Exception Exception { get; } }
除了上面的審計,你也可使用經過這些事件,實現保存以前的自動更新數據庫字段的值,好比 Add
或 Update
操做數據時自動設置更新時間等信息htm
本文提到的特性還未正式發佈,預計會在 .net5 下一個預覽版中發佈,若是想如今要嘗試,請使用 efcore 的 daily build 的包,能夠參考 https://github.com/dotnet/aspnetcore/blob/master/docs/DailyBuilds.mdblog