.Net Core 微服务实战 - 工作单元模式

源码及系列文章目录

Git 源码https://github.com/tangsong1995/TS.Microservices
CSDN 资源https://download.csdn.net/download/qq_33649351/34675095

系列文章目录https://blog.csdn.net/qq_33649351/article/details/120998558

工作单元模式的特性

工作单元模式有以下几个特性:

  • 使用同一上下文
  • 跟踪实体的状态
  • 保障事务一致性

实现工作单元模式

定义 IUnitOfWork 接口

public interface IUnitOfWork : IDisposable
{
    Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
    Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default);
}

IUnitOfWork 定义了两个接口:SaveChangesAsyncSaveEntitiesAsync。SaveChangesAsync 接口返回受影响行数,SaveEntitiesAsync 接口返回保存是否成功结果。

定义 ITransaction 事务管理接口

public interface ITransaction
{
    IDbContextTransaction GetCurrentTransaction();

    bool HasActiveTransaction { get; }

    Task<IDbContextTransaction> BeginTransactionAsync(ICapPublisher capBus);

    Task CommitTransactionAsync(IDbContextTransaction transaction);

    void RollbackTransaction();
}

GetCurrentTransaction:获取当前事务
HasActiveTransaction :判断当前事务是否开启
BeginTransactionAsync:开启事务
CommitTransactionAsync:提交事务
RollbackTransaction:回滚事务

使用EF实现工作单元模式 EFContext

public class EFContext : DbContext, IUnitOfWork, ITransaction
{
    protected IMediator _mediator;

    public EFContext(DbContextOptions options, IMediator mediator) : base(options)
    {
        _mediator = mediator;
    }

    #region IUnitOfWork
    public async Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default)
    {
        var result = await base.SaveChangesAsync(cancellationToken);
        return true;
    }
    #endregion

    #region ITransaction

    private IDbContextTransaction _currentTransaction;
    public IDbContextTransaction GetCurrentTransaction() => _currentTransaction;
    public bool HasActiveTransaction => _currentTransaction != null;
    public Task<IDbContextTransaction> BeginTransactionAsync(ICapPublisher capBus)
    {
        if (_currentTransaction != null) return null;
        _currentTransaction = Database.BeginTransaction(capBus, autoCommit: false);
        return Task.FromResult(_currentTransaction);
    }

    public async Task CommitTransactionAsync(IDbContextTransaction transaction)
    {
        if (transaction == null) throw new ArgumentNullException(nameof(transaction));
        if (transaction != _currentTransaction) throw new InvalidOperationException($"Transaction {transaction.TransactionId} is not current");

        try
        {
            await SaveChangesAsync();
            transaction.Commit();
        }
        catch
        {
            RollbackTransaction();
            throw;
        }
        finally
        {
            if (_currentTransaction != null)
            {
                _currentTransaction.Dispose();
                _currentTransaction = null;
            }
        }
    }

    public void RollbackTransaction()
    {
        try
        {
            _currentTransaction?.Rollback();
        }
        finally
        {
            if (_currentTransaction != null)
            {
                _currentTransaction.Dispose();
                _currentTransaction = null;
            }
        }
    }


    #endregion
}

EFContext 继承了EF基类 DbContext ,并且实现了 IUnitOfWork, ITransaction 接口。

管理事务

定义 TransactionBehavior 管理事务:

public class TransactionBehavior<TDbContext, TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TDbContext : EFContext
{
    ILogger _logger;
    TDbContext _dbContext;
    ICapPublisher _capBus;
    public TransactionBehavior(TDbContext dbContext, ILogger logger, ICapPublisher capBus)
    {
        _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        _capBus = capBus ?? throw new ArgumentNullException(nameof(capBus));
    }


    public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
    {
        var response = default(TResponse);
        var typeName = request.GetGenericTypeName();

        try
        {
            if (_dbContext.HasActiveTransaction)
            {
                return await next();
            }

			// 定义数据路操作执行的策略
            var strategy = _dbContext.Database.CreateExecutionStrategy();

            await strategy.ExecuteAsync(async () =>
            {
                Guid transactionId;
                using (var transaction = await _dbContext.BeginTransactionAsync(_capBus))
                using (_logger.BeginScope("TransactionContext:{TransactionId}", transaction.TransactionId))
                {
                    _logger.LogInformation("----- 开始事务 {TransactionId} ({@Command})", transaction.TransactionId, typeName, request);

                    response = await next();

                    _logger.LogInformation("----- 提交事务 {TransactionId} {CommandName}", transaction.TransactionId, typeName);


                    await _dbContext.CommitTransactionAsync(transaction);

                    transactionId = transaction.TransactionId;
                }
            });

            return response;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "处理事务出错 {CommandName} ({@Command})", typeName, request);
            throw;
        }
    }
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值