TransactionScope,EF DbContext和Dirty Read

时间:2012-12-07 22:51:35

标签: c# entity-framework-4 transactionscope

过去几个小时我一直在谷歌搜索答案,但没有找到答案,所以我希望有人能指出我正确的方向。

我想知道如何在TransactionScope中使用EF DbContext(代码优先)进行脏读。例如

DbContext context = new MyEntities();
using(TransactionScope scope = new TransactionScope())
{
    context.SomeTable.Add(someObject);
    context.SaveChanges();

    var objects = context.SomeTable.Where(...).Select(...); //times out here on the read, because the write above locks the tables
    //modify each object
    context.SaveChanges();

    scope.Complete(); //transaction is a success only if the entire batch succeeds
}

我尝试使用以下内容包装read调用:

using(TransactionScope scope2 = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions{IsolationLEvel = IsolationLevel.ReadUncommitted}))
{
    var objects = context.SomeTable.Where(...).Select(...); //times out here on the 
}

什么是正确的方法?

3 个答案:

答案 0 :(得分:1)

它终于找到了我的问题所在:EF没有像TransactionScope那样与L2S很好地集成。这意味着EF会为需要服务器的每个操作打开和关闭连接(保存更改或查询)。

这可以获得分布式事务和分布式死锁。

要解决此问题,请手动打开和关闭EF StoreConnection,以确保在交易期间只有一个连接。

答案 1 :(得分:1)

您可以像这样设置TransactionScope的IsolationLevel ......

var transactionOptions = new System.Transactions.TransactionOptions();
transactionOptions.Timeout = new TimeSpan(0, 0, 30);
transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted;
using (var transactionScope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required, transactionOptions))
{
...
}

答案 2 :(得分:0)

您可以在服务器上执行alter database your_db_name set READ_COMMITTED_SNAPSHOT on;(可从SQLServer 2005获得),读者不会被读者阻止(假设在read committed隔离级别读取事务)。