efcore 新特性 SaveChanges Events
Intro
昨天早上看到之前關(guān)注的一個 efcore 的 issue 被 closed 捐寥,于是看了一眼, ef core 新合并了一個 PR,在 DbContext
中增加了 SaveChanges
相關(guān)的幾個事件萨蚕,具體的變更可以參數(shù) PR https://github.com/dotnet/efcore/pull/21862
Events
之前寫過兩篇關(guān)于 EF Core 做自動審計的文章酱虎,但是不夠靈活
第一次的實現(xiàn)需要顯示繼承一個 AuditDbContext
,在有些需要沒辦法修改 DbContext
或者原有 DbContext
已經(jīng)有繼承某一個類松蒜,就沒有辦法用了
后面使用 AOP 改進(jìn)了一版扔茅,通過一個審計切面邏輯完整自動審計,但是需要引入 AOP 組件支持秸苗,對于不想引入額外組件的項目來說也并非特別友好
在這個變更之后召娜,我們可以通過 SavingChanges
事件獲取保存之前 DbContext
的狀態(tài),通過 SavedChanges
事件來獲取保存成功的事件惊楼,SaveChangesFailed
事件獲取保存失敗事件
事件定義如下:
/// <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;
事件參數(shù)定義如下:
/// <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; }
}
More
除了上面的審計玖瘸,你也可以使用通過這些事件,實現(xiàn)保存之前的自動更新數(shù)據(jù)庫字段的值檀咙,比如 Add
或 Update
操作數(shù)據(jù)時自動設(shè)置更新時間等信息
本文提到的特性還未正式發(fā)布雅倒,預(yù)計會在 .net5 下一個預(yù)覽版中發(fā)布,如果想現(xiàn)在要嘗試弧可,請使用 efcore 的 daily build 的包蔑匣,可以參考 https://github.com/dotnet/aspnetcore/blob/master/docs/DailyBuilds.md