【问题标题】:'dirty read' not working during transaction scope set with readuncommitted isolation level“脏读”在事务范围设置为未提交的隔离级别期间不起作用
【发布时间】:2012-02-02 17:21:24
【问题描述】:

我有一个类似这样的代码:

using (TransactionScope scope = 
   new TransactionScope(TransactionScopeOption.Required), new TransactionOptions)
{ 

    IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
    // "dirty" read  for test purposes , to see if my 
    // select will actually select the information I just inserted

    actual = target.GetCostCentersRates(accountId);

}

这不起作用,我已经测试了查询,并且在提交数据时它们可以有效地工作,但是当它没有提交时,它会出现不允许我检查脏读的问题,即使隔离级别设置为未提交。 我想弄清楚为什么我不能访问这些信息,因为我不能以任何方式将信息提交到我们的数据库,因为这是一种测试方法。
谢谢!

这就是全部内容

 public void GetCostCentersRatesTest()
    {

        using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommited }))
        {
            //Arrange
            BRL.AdministrativeArea.SystemClientBusinessRole systemClient = new BRL.AdministrativeArea.SystemClientBusinessRole();
            int systemClientId = systemClient.InsertSystemClient(systemClientInfo).systemClientId;
            BRL.BRLProperties.systemClientId = systemClientId;
            employeeInfo.multiCompaniesInfo.systemClientId = systemClientId;
            int stateId = 1;
            int cityId = 1;
            int functionId = 1;
            employeeInfo.stateId = stateId;
            employeeInfo.cityId = cityId;
            employeeInfo.functionId = functionId;
            int employeeId = employees.InsertEmployeers(employeeInfo);
            BRL.BRLProperties.employeeId = employeeId;
            IActionReturnInfo actionAccount = (accounts.InsertAccountPlan(accountPlanInfo));
            int accountId = Convert.ToInt32(actionAccount.UpdateDataSourceList[0].ToString());
            clientInfo.stateId = stateId;
            clientInfo.cityId = cityId;
            clientInfo.stateIdCorrespondency = stateId;
            clientInfo.cityIdCorrespondency = cityId;
            clientInfo.stateIdDelivery = stateId;
            clientInfo.cityIdDelivery = cityId;
            clientInfo.multiCompaniesInfo.systemClientId = systemClientId;
            clientInfo.multiCompaniesInfo.employeeId = employeeId;
            int clientId;
            clients.InsertClient(clientInfo, out clientId);
            centerCostInfo.systemClientId = systemClientId;
            centerCostInfo.clientId = clientId;
            centerCostInfo.employeeId = employeeId;
            centerCostInfo.directorID = employeeId;
            centerCostInfo.managerID = employeeId;
            centerCostInfo.multiCompaniesInfo.systemClientId = systemClientId;
            centerCostInfo.multiCompaniesInfo.employeeId = employeeId;
            IActionReturnInfo action = new CenterCostsBusinessRole().InsertCostCenter(centerCostInfo);
            int centerCostId = Convert.ToInt32(action.UpdateDataSourceList[0].ToString());
            rate.accountId = accountId;
            rate.centerCostId = centerCostId;
            costCenterRates.Add(rate);
            int costCenterRateId;
            AccountBusinessRole target = new AccountBusinessRole();
            DataSet actual;

             IActionReturnInfo costCenterRateAction = accounts.InsertCenterCostRates(costCenterRates);
                costCenterRateId = Convert.ToInt32(costCenterRateAction.UpdateDataSourceList[0].ToString());

                //Act
                actual = target.GetCostCentersRates(accountId);



            //Assert
            Assert.IsTrue(FindInDataset(costCenterRateId, actual, "ACCOUNTID"));
        }
    }

.....

【问题讨论】:

  • 这是否触及某种数据库后端?如果是这样 - 哪一个?
  • 我尝试重新格式化您的代码以提高可读性,但在这样做的过程中,我发现它没有任何意义。您正在设置 IsolationLevel 而没有使用它。您已经声明了scope,但也没有使用它。您可以直接从 IDE 中复制代码,然后将其粘贴到问题中。然后突出显示它并按“代码”按钮。这样,SO 将完全按照从 IDE 中出来的方式美化您的代码。
  • 我在 TransactionScope 构造函数上设置了隔离级别。
  • 我不使用变量范围,因为我使用了 "using" ,但是,我将复制我的整个方法来展示。谢谢1
  • 数据库后端是什么意思?唯一发生的事情是,当我尝试脏读时,我在事务中插入的数据没有出现,我不确定我是否理解了这个问题!

标签: c# c#-4.0 transactionscope isolation-level transaction-isolation


【解决方案1】:

让脏读工作。 您开始交易(明确) 将更改推送到数据库

在另一个带有 readuncommitted 的事务中 选择数据,你也会得到未提交的东西。

然后你要么回滚要么提交你在其中进行更改的事务。

所以说 sql server manager 启动查询

Start Transaction
Insert SomeTable(500)

启动另一个查询

Select * from SomeTable With(READUNCOMMITTED)

您将看到 500 条记录。

老实说,试图弄清楚你为什么要这样做,ADO.Net 使用的断开连接模型使得它除了分布式事务之外没有必要,而且你不会像这样测试它们。如果您要测试的只是插入,那么就这样做,听起来几乎就像您在实时数据库上进行测试一样,这是非常糟糕的事情。

【讨论】:

  • 我们只是想用一些东西来测试我们所有的方法,因为我们的方法处理数据,在这种情况下我们需要知道,例如,如果选择正确过滤信息.要执行选择,我们必须模拟插入以保证数据库中存在实际数据。这只会在我们的开发(测试)数据库中完成
  • 好吧,为什么不能直接将数据提交到测试数据库。当你搞砸这个时,你并没有测试你正在使用的东西。哦,readuncommitted 是一个提示,dbms 可能会忽略它。
  • 哦,这可能是问题所在。好吧,事情是我只是听从命令,我认为他们最终会在我们的最终版本上进行测试并使用它来确保在编译该版本时功能齐全。这就是我们使用事务范围的原因,所以我们不提交任何东西。目前,我们不需要它,因为使用的是测试数据库,但我想将来......谁知道。老板的命令!
  • 好了,问题解决了!有人更改了其中一个存储过程,我得到了一些数据不一致,这不是我的隔离级别的问题!谢谢!
  • 我无法解释为什么你的老板让你跳过这一系列的障碍。当我担任那个职位时,我会问,我坚持要一个明智的答案,否则我就无法做好我的工作。 PS 我从来都不相信老板最清楚,在我的经验中很少是真的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-05
  • 1970-01-01
  • 2020-08-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多