持久化事件订阅


  持久化事件订阅是指实体插入、修改或删除时,会通知订阅器做相应的处理。事件会在动作发生之前及之后进行触发。使用订阅器可以使业务逻辑解耦,比如删除数据前的逻辑判断,数据创建成功后的各种协调处理等等。

  PersistentSubscriberAsyncPersistentSubscriber 类分别是同步订阅器和异步订阅器抽象类,你继承此类实现方法的重写即可。如下所示:

private class MySubscriber : PersistentSubscriber
{
    protected override bool OnBeforeCreate(IEntity entity)
    {
        return true;
    }

    protected override void OnAfterCreate(IEntity entity)
    {
    }

    protected override bool OnBeforeUpdate(IEntity entity)
    {
        return true;
    }

    protected override void OnAfterUpdate(IEntity entity)
    {
    }


    protected override bool OnBeforeRemove(IEntity entity)
    {
        return true;
    }

    protected override void OnAfterRemove(IEntity entity)
    {
    }

    protected override bool OnBeforeBatch(IEnumerable<IEntity> entities, PersistentOperator operater)
    {
        return true;
    }

    protected override void OnAfterBatch(IEnumerable<IEntity> entities, PersistentOperator operater)
    {
    }

    protected override void OnCreate(Type entityType)
    {
    }

    protected override void OnUpdate(Type entityType)
    {
    }

    protected override void OnRemove(Type entityType)
    {
    }
}

  • OnBeforeCreate 在实体插入之前触发,如果你想阻止实体插入,则可以返回 false。

  • OnAfterCreate 在实体插入之后触发。

  • OnBeforeUpdate 在实体更新之前触发,如果你想阻止实体更新,则可以返回 false。

  • OnAfterUpdate 在实体更新之后触发。

  • OnBeforeRemove 在实体删除之前触发,如果你想阻止实体删除,则可以返回 false。

  • OnAfterRemove 在实体删除之后触发。

  • OnBeforeBatch 在批量操作之前触发,根据 PersistentOperator 判断是新增、修改还是删除。如果你想阻止批量操作,则可以返回 false。

  • OnAfterBatch 在批量操作之后触发,根据 PersistentOperator 判断是新增、修改还是删除。

  OnCreate、OnUpdate、OnRemove 仅仅捕获实体类型,不针对具体的实体对象。OnBeforeBatch 和 OnAfterBatch 时也会触发相应的方法。


  实现完订阅器后,使用 PersistentSubscribeManager 类的 AddSubscriber 或 AddAsyncSubscriber 方法添加订阅器。如下所示:

[TestMethod]
public void TestAddSubscriber()
{
    PersistentSubscribeManager.AddSubscriber(s => new MySubscriber().Accept(s));
    //PersistentSubscribeManager.AddAsyncSubscriber(s => new MyAsyncSubscriber().AcceptAsync(s));
}

  .Net Core 应用程序中,你可以在 Startup.ConfigureServices 方法里使用扩展方法 AddPersistentSubscriber 或 AddAsyncPersistentSubscriber 来添加订阅器。如下所示:

namespace demo
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddFireasy(Configuration).AddIoc();

            services.AddSubscriber<MySubscriber>();
            //services.AddAsyncSubscriber<MyAsyncSubscriber>();
        }
    }
}

  使用这种方式注入的订阅器,是支持构造函数注入的,你可以在构造函数里将 EntityContext 实例注入进来。

  AddSubscriber 和 AddAsyncSubscriber 方法支持 EntityContextPersistentSubject 过滤,使得管理订阅管理器能够决定哪些订阅器可以接收事件消息。如下所示:

namespace demo
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddFireasy(Configuration).AddIoc();

            //DbContext 触发,只订阅 Org 实体的相关消息
            services.AddSubscriber<DbContext, MySubscriber>(s => s.EntityType == typeof(Org));
        }
    }
}

  默认是关闭事件订阅的,你可以在 EntityContextOptions 参数里设置 NotifyEvents 开启,请参阅 配置 EntityContextOptions。开启后,你可以需要关闭的地方使用 DisableSubscribeScope 对象来暂时关闭订阅通知。如下所示:

[TestMethod]
public void TestDisableSubscriber()
{
    using (var db = new DbContext())
    using (var scope = new DisableSubscribeScope(
        PersistentEventType.BeforeCreate,
        PersistentEventType.AfterCreate))
    {
        var product = db.Products.Get(1);
        product.ProductName = "fireasy";
        db.Products.Update(product);
    }
}

  DisableSubscribeScope 的构造函数可以传入需要禁用的事件类型,如果不指定则禁用所有事件。