记一次EF+Mysql所遇到的事务不生效的的坑

业务场景:

    近期写的一个项目,整个项目采用的DDD(领域驱动)设计,所以刚开始设计的时候就将各个业务以聚合根的方式进行划分,以该业务场景为例,整体的业务简述为,当客户进行付款以后,创建一个付款单,然后由财务手动将付款单与发货单进行账务冲抵和关联,同时还需要针对付款的客户及企业的余额进行相应的变动,所以,当付款单和发货单进行冲抵业务的时候,客户及其企业的待付款金额将会根据冲抵的金额,进行变动,所以该业务的主要操作是首先针对发货单的待付款金额进行冲抵扣减,此时操作的聚合根为发货单的聚合根,而因为还需要同时针对用户的账户金额进行变动,所以在操作发货单的聚合根的时候,触发一个领域事件,而用户的聚合根订阅该事件,当该事件被触发的时候,用户的聚合根接收到事件,并随之进行相应的操作。

实现方式:

     一般情况下,领域事件可以看作一个一对多的多播事件即一方触发多方进行响应,一个聚合根发生改变并且触发领域事件的时候,其他与之关联的聚合根都将订阅该事件,在被触发的时候进行响应并对自身进行对应的操作,而且事件一般不会存在返回值的情况,所以订阅方的业务是否执行成功,失败后需要进行什么样的操作,可以根据业务的不同进行不同的操作,如果是需要强一致性的业务,就需要考虑操作异常的处理。如果是一致性不强的业务,则可以考虑自身重试等机制。而目前该项目所遇到的就是强一致性的业务需求,那么只能一荣俱荣,一损俱损。
在领域事件的是先方面,我采用的是NetCore项目中比较流行的MediatR组件(一种简单的实现进程内的消息传递机制的类库),采用MediatR的消息通知机制,在进行数据操作的时候,添加并触发领域事件,从而实现领域事件的触发以及订阅处理,同时采用EF的事务来确保数据库在操作数据时候的一致性。

    //业务代码

    /// <summary>
    /// 业务开始
    /// </summary>
    /// <returns></returns>

    public async Task Task(CancellationToken token=default)
    {
   
        // 下面所用的未声明对象均有DI生成。
        // DbCotext 继承 IUnitOfWork,并且通过IOC将其生命周期设为Scope(请求域) 
        //_repository 为聚合根的仓储类,在实例化时注入IUnitOfWork进行相应的数据库操作。
        //具体略
        var db = _repository.UnitOfWork as TestDbContext;
        using (var transaction=await db.Database.BeginTransactionAsync(IsolationLevel.ReadCommitted,token))
        {
   
            A a = new A();
            a.AddDomainEvent(new TestEvent());
            await _repository.AddAsync(a);
            await
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值