如何防止死锁以及如何在实体框架中设置隔离级别?

时间:2014-08-20 00:41:47

标签: c# asp.net-mvc linq entity-framework

我的应用程序中有很多死锁(asp.net mvc,实体框架代码优先)

所以我发现了一些关于死锁的博客文章。在一篇博文中,here建议使用

 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

dbcontext.database.executesqlcommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;")

我在sql server上执行此sql命令,然后检查未提交读取的事务隔离级别。

但是当我使用ef和linq运行代码并在运行“set transaction”的行之后设置断点并返回sql检查trnasaction级别时,它仍然被读取提交,并且我有这么多死区。 / p>

我找到的另一个解决方案是here,建议使用范围来设置隔离级别

using (var scope = new TransactionScope(TransactionScopeOption.Required, new 
      TransactionOptions { IsolationLevel= IsolationLevel.Snapshot }))
    {

    // do something with EF here
    scope.Complete();
    }

但是在使用每个请求上下文时是否可以使用范围?

第一个问题是为什么事务级别在设置为通过dbcontext未提交读取后仍然被读取?

第二个问题是,在这个blog post中,它提到设置隔离级别是按上下文这是否意味着在处理dbcontext隔离级别之后会返回read committed?

最后我首先使用ef代码v6,并且使用了unity来为每个请求生成dbcontext我还有其他选项,所以我避免了这么多的死区?

1 个答案:

答案 0 :(得分:2)

首先,检查deadlocks的来源。这将帮助您找到问题所在 - 您需要修复的区域。

有时ORM存在复杂逻辑问题。一个选项是provide Entity Framework with a stored procedure用于读取和写入更多数据密集型表。

在您的控制器或存储库层中,您可以execute a stored procedure这样:

Context.Database.SqlQuery<MyEntityType>("Exec mySpName \@p0, \@p1", param1, param2);

您还可以将Database.ExecuteSqlCommand用于不返回数据的过程。

存储过程通常有performance gains from execution plan caching

使用Read Uncommitted不是一个神奇的子弹,但是如果你真的不关心可能返回错误数据的脏读,那么你可以保证你的存储过程不会通过设置序列化来获取读锁或使用NoLock提示。