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 已经有继承某一个类,就没有办法用了,可以参考 EF Core 数据变更自动审计设计

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

在这个 PR 合并之后,我们可以通过 SavingChanges 事件获取保存之前 DbContext 的状态,通过 SavedChanges 事件来获取保存成功后的 DbContext 信息,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;

事件参数定义如下:

/// <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

除了上面的审计,你也可以使用通过这些事件,实现保存之前的自动更新数据库字段的值,比如 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值