如何处理多个存储库的服务级别事务

问题描述 投票:0回答:1

我有一个项目,需要从服务级别创建事务并在多个存储库类中使用它。一些存储库从内部调用其子存储库。

有一个主要的管理存储库,用于管理存储库之间的一些通信(就像服务应该如何,但由于我有依赖性问题,所以决定选择这条路径)。 目前,我创建并处理来自此管理存储库的事务。但这阻碍了正确测试用例的创建。

注意:我在存储库中结合使用了 ef core 和 Dapper。并不是说这可能是一个问题,只是说而已。

这是我目前尝试过的,但由于结构的原因,我无法正确测试控制器。 这是因为当我模拟管理存储库时,我可以调用子存储库。但是当我不模拟它时,创建事务会抛出错误。

我知道有一些变通方法可以用这种结构来测试它。 但是有什么办法可以将交易处理移至专用存储库吗? 这是一个好的方法吗?

`公共类 ManagementRepo : IManagementRepo { 私有只读 MyDBContext _context; 私有 IDbContextTransaction _currentTransaction; // 仅在创建事务时初始化

public ManagementRepo(MyDBContext context /* other dependencies */)
{
    _context = context;
    // other initializations
}

public async Task BeginTransactionAsync()
{
    _currentTransaction = await _context.Database.BeginTransactionAsync();
}

public async Task CommitTransactionAsync()
{
    if (_currentTransaction != null)
    {
        await _currentTransaction.CommitAsync();
        await _currentTransaction.DisposeAsync();
        _currentTransaction = null;
    }
}

public async Task RollBackTransactionAsync()
{
    if (_currentTransaction != null)
    {
        await _currentTransaction.RollbackAsync();
        await _currentTransaction.DisposeAsync();
        _currentTransaction = null;
    }
}

public IDbTransaction GetCurrentTransaction()
{
    return _currentTransaction?.GetDbTransaction();
}

public async Task<bool> SomeMethod(/* params */)
{
    var res1 = await otherRepo.SomeMethod();
    var res2 = await otherRepo.SomeOtherMethod();
    /*
        Other logic
        ...
    */
    // return a value or handle the result
}

} `

服务层 `public async Task UpdateService(/* 参数 */) { 等待 _ManagementRepo.BeginTransactionAsync(); 尝试 { var res = wait _ManagementRepo.SomeMethod(recordId, tableList); 如果(!res) { 抛出新的异常(“无法更新资产”); }

    // Commit transaction
    await _ManagementRepo.CommitTransactionAsync();

    var asset = await _ManagementRepo.GetMethod(recordId);
    return asset;
}
catch (Exception)
{
    // Rollback in case of an error
    await _ManagementRepo.RollBackTransactionAsync();
    throw;
}

} `

sql-server entity-framework-core xunit
1个回答
0
投票

我认为您可能想要做的是在逻辑顶层的流程模式样式中使用

TransactionScope
来包含所有单个数据库事务。

using (TransactionScope scope = new TransactionScope())
{
    //do all required stuff here
    ...
    scope.Complete();//commit top layer transaction
}

请注意,由于您很可能要在不同的连接上进行操作,事务很可能会被提升为分布式事务,所以我建议您阅读一些MSDTC分布式事务 - https://learn .microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc771686(v=ws.10)?redirectedfrom=MSDN

这里是有关

TransactionScope
的文档 - https://learn.microsoft.com/en-us/dotnet/api/system.transactions.transactionscope

© www.soinside.com 2019 - 2024. All rights reserved.