业务层中的TransactionScope用于脏异步读取

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

我正在开发.NET Core web api服务并在BL中使用以下方法:

public async Task<SetParams> GetParams(CreateRequest request)
        {
            var user = await _userRepository.GetUserByLogin(request.Login);  
            var client = await _clientRepository.GetClientByCode( request.ClientCode);

            // many other getters here 

            return new SetParams
            {
                IdUser = user.IdUser,
                ClientName = client.Name,
                // and so forth...
            };
        }

我要求所有实体都处于“脏读”模式。

所以,我试图以这种方式使用TransactionScope:

public async Task<SetParams> GetParams(CreateRequest request)
        {
            using (var ts = new TransactionScope(
                TransactionScopeOption.Required,
                new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted }))
            {
                var user = await _userRepository.GetUserByLogin(request.Login);
                var client = await _clientRepository.GetClientByCode(request.ClientCode);

                // many other getters here 

                ts.Complete();

                return new SetParams
                {
                    IdUser = user.IdUser,
                    ClientName = client.Name,
                    // and so forth...
                };
            }
        }

但是:1)这已经读取了提交模式(我从this post知道我必须启动一个事务,但我这里没有会话或数据库上下文,因为我在BL中不在DAL中)

2)以异常结束必须将TransactionScope放置在创建它的同一个线程上。

c# transactions transactionscope nolock
1个回答
1
投票

您需要事务处理的Read查询集(脏读)

我假设你有很高的并发性来读取未提交的数据。这可能是在Select查询中使用事务的唯一用例。我认为它们仍然与少数DML操作交织在一起

从哪里开始Transaction,BL / DAL,它需要DbContext吗?

这取决于您的用例,如果您的设计是从BL分配多个业务查询(应该是事务的一部分),那么它是一个有效的起点,尤其是使用Ambient事务(TransactionScope)。用于启动事务的显式SessionContext是其中一种机制,因为所有共享查询都在同一个事务上下文中无缝地登记,但使用TransactionScopeCommittableTransaction可能类似,您可以使用TransactionScopeOption来确保各种查询的参与:

  1. 使用Requires New使用Required在BL和DAL级别启动环境事务,以确保使用相同的事务上下文进行登记。数据库连接应自动登记在可用范围内。
  2. 使用CommittableTransaction,在BL中创建的同一对象被传递到DAL存储库,并且显式登记了Connection对象
  3. 如果你的需求稍微具体一点,那么在没有提交是可行的情况下,直到完成所有Child操作在不同的线程上,然后查看DependantTransaction,它也是System.Transaction的一部分,但是它做了更紧密的绑定,主要用于多线程场景,Async Await调用可能不需要它,因为只有在所有awaits完成时才完成。

与A TransactionScope相关的问题必须放在与其创建的同一个线程上。

解决方案是here,这是在.Net4.5.1中引入的,并确保在异步调用中使用TransactionScope

查询的SQL Server隔离级别

您所指的是大多数系统ReadCommitted的默认设置,但您当然可以调整设置以确保更低的IsolationLevel,同时还要准备好在应用程序中读取脏数据的含义

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