zoukankan      html  css  js  c++  java
  • 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 已经有继承某一个类,就没有办法用了,可以参考 https://www.cnblogs.com/weihanli/p/auto-audit-for-entity-framework.html

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

    在这个 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

  • 相关阅读:
    虚拟机安装VMware Tools
    SVN源码泄露漏洞
    为什么站点使用https加密之后还能看到相关数据
    AWVS11使用教程——Acunetix Web Vulnerability Scanner 11.x
    接口测试_RESTClient基本使用
    【pwnable.kr】coin1
    【pwnable.kr】 mistake
    【pwnable.kr】leg
    【pwnable.kr】random
    【pwnable.kr】passcode
  • 原文地址:https://www.cnblogs.com/weihanli/p/13416219.html
Copyright © 2011-2022 走看看