efcore 新特性 SaveChanges Events


efcore 新特性 SaveChanges Events

Intro

昨天早上看到之前关注的一个 efcore 的 issue 被 closed ,于是看了一眼, ef core 新合并了一个 PR,在 DbContext 中增加了 SaveChanges 相关的几个事件,具体的变更可以参数 PR https://github.com/dotnet/efcore/pull/21862

Events

之前写过两篇关于 EF Core 做自动审计的文章

第一次的实现需要显式继承一个 AuditDbContext ,在有些需要没办法修改 DbContext 或者原有 DbContext 已经有继承某一个类,就没有办法用了,可以参考

后面结合 AOP 改进了一版,通过一个审计切面逻辑完成自动审计,但是需要引入 AOP 组件支持,对于不想引入额外组件的项目来说也并非特别友好,可以参考

在这个 PR 合并之后,我们可以通过 SavingChanges 事件获取保存之前 DbContext 的状态,通过 SavedChanges 事件来获取保存成功后的 DbContext 信息,SaveChangesFailed 事件获取保存失败信息

事件定义如下:


/// 
///     An event fired at the beginning of a call to  or 
/// 
public event EventHandler SavingChanges;

/// 
///     An event fired at the end of a call to  or 
/// 
public event EventHandler SavedChanges;

/// 
///     An event fired if a call to  or  fails with an exception.
/// 
public event EventHandler SaveChangesFailed;

事件参数定义如下:

/// 
///     Base event arguments for the  and  events.
/// 
public abstract class SaveChangesEventArgs : EventArgs
{
    /// 
    ///     Creates a base event arguments instance for 
    ///     or  events.
    /// 
    ///  The value passed to SaveChanges. 
    protected SaveChangesEventArgs(bool acceptAllChangesOnSuccess)
    {
        AcceptAllChangesOnSuccess = acceptAllChangesOnSuccess;
    }

    /// 
    ///     The value passed to  or .
    /// 
    public virtual bool AcceptAllChangesOnSuccess { get; }
}

/// 
///     Event arguments for the  event.
/// 
public class SavingChangesEventArgs : SaveChangesEventArgs
{
    /// 
    ///     Creates event arguments for the  event.
    /// 
    ///  The value passed to SaveChanges. 
    public SavingChangesEventArgs(bool acceptAllChangesOnSuccess)
        : base(acceptAllChangesOnSuccess)
    {
    }
}

/// 
///     Event arguments for the  event.
/// 
public class SavedChangesEventArgs : SaveChangesEventArgs
{
    /// 
    ///     Creates a new  instance with the given number of entities saved.
    /// 
    ///  The value passed to SaveChanges. 
    ///  The number of entities saved. 
    public SavedChangesEventArgs(bool acceptAllChangesOnSuccess, int entitiesSavedCount) : base(acceptAllChangesOnSuccess)
    {
        EntitiesSavedCount = entitiesSavedCount;
    }

    /// 
    ///     The number of entities saved.
    /// 
    public virtual int EntitiesSavedCount { get; }
}

/// 
///     Event arguments for the  event.
/// 
public class SaveChangesFailedEventArgs : SaveChangesEventArgs
{
    /// 
    /// Creates a new  instance with the exception that was thrown.
    /// 
    ///  The value passed to SaveChanges. 
    ///  The exception thrown. 
    public SaveChangesFailedEventArgs(bool acceptAllChangesOnSuccess, [NotNull] Exception exception)
        : base(acceptAllChangesOnSuccess)
    {
        Exception = exception;
    }

    /// 
    /// The exception thrown during or .
    /// 
    public virtual Exception Exception { get; }
}

More

除了上面的审计,你也可以使用通过这些事件,实现保存之前的自动更新数据库字段的值,比如 AddUpdate 操作数据时自动设置更新时间等信息

本文提到的特性还未正式发布,预计会在 .net5 下一个预览版中发布,如果想现在要尝试,请使用 efcore 的 daily build 的包,可以参考 https://github.com/dotnet/aspnetcore/blob/master/docs/DailyBuilds.md

Reference

  • https://github.com/dotnet/efcore/issues/15910
  • https://github.com/dotnet/efcore/pull/21862