2009-05-29 72 views
127

实体框架如何使用在实体框架的NOLOCK功能? XML是唯一的方法吗?与NOLOCK

回答

196

没有,但你可以开始交易,并设置isolation level to read uncommited。这与NOLOCK基本相同,但不是以每个表为基础进行操作,而是针对事务范围内的所有内容执行操作。

如果这听起来像你想要的东西,这里是你怎么会去这样做......

//declare the transaction options 
var transactionOptions = new System.Transactions.TransactionOptions(); 
//set it to read uncommited 
transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted; 
//create the transaction scope, passing our options in 
using (var transactionScope = new System.Transactions.TransactionScope(
    System.Transactions.TransactionScopeOption.Required, 
    transactionOptions) 
) 

//declare our context 
using (var context = new MyEntityConnection()) 
{ 
    //any reads we do here will also read uncomitted data 
    //... 
    //... 
    //don't forget to complete the transaction scope 
    transactionScope.Complete(); 
} 
+0

优秀的@DoctaJonez EF4中引入了什么新东西? – FMFF 2012-02-21 22:03:14

+0

@FMFF我不知道是否为EF4引入了新的东西。我知道上面的代码适用于EFv1及更高版本。 – 2012-02-28 16:08:36

2

不,不是真的 - 实体框架基本上是上述实际的数据库中的相当严格的层。您的查询,制定ESQL - 实体SQL - 这是第一个针对所有对你的实体模型,由于EF支持多种数据库后端,你不能真正直接发送“本地”的SQL后端。

的NOLOCK查询提示是SQL Server特定的事情,也不会在任何其他支持的数据库的工作(除非他们也已经实现了相同的提示 - 我强烈怀疑)。

马克

+0

此答案已过时 - 您可以像其他人提到的那样使用NOLOCK,并且可以使用Database.ExecuteSqlCommand()或DbSet .SqlQuery()执行“本机”SQL。 – Dunc 2016-03-08 10:20:18

+1

@Dunc:感谢downvote - 顺便说一句:你应该不***使用`(NOLOCK)`反正 - 看到[坏习惯踢 - 把NOLOCK无处不在](http://blogs.sqlsentry.com/ aaronbertrand/bad-habits-nolock-everywhere /) - 这是***不推荐***在任何地方使用 - 完全相反! – 2016-03-08 10:38:42

+0

不客气。 – Dunc 2016-03-08 10:55:54

5

为了避开这个我创建数据库视图和视图的查询申请NOLOCK。然后我将视图视为EF中的表格。

26

如果您需要在大的东西,我们发现这不是每次实际启动一个TransactionScope较少侵入的最好方式,是简单地通过运行这个设置你的连接上的默认事务隔离级别您已经创建了对象上下文后简单的命令:

this.context.ExecuteStoreCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;"); 

http://msdn.microsoft.com/en-us/library/aa259216(v=sql.80).aspx

利用这种技术,我们能够创建一个为我们创造了上下文简单EF供应商,使我们”每一次实际运行此命令为我们所有的上下文在默认情况下,始终处于“未提交读取”状态。

74

扩展方法可以使这更容易

public static List<T> ToListReadUncommitted<T>(this IQueryable<T> query) 
{ 
    using (var scope = new TransactionScope(
     TransactionScopeOption.Required, 
     new TransactionOptions() { 
      IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted })) 
    { 
     List<T> toReturn = query.ToList(); 
     scope.Complete(); 
     return toReturn; 
    } 
} 

public static int CountReadUncommitted<T>(this IQueryable<T> query) 
{ 
    using (var scope = new TransactionScope(
     TransactionScopeOption.Required, 
     new TransactionOptions() { 
      IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted })) 
    { 
     int toReturn = query.Count(); 
     scope.Complete(); 
     return toReturn; 
    } 
} 
18

虽然我绝对同意,使用读未提交的事务隔离级别是最好的选择,但你不得不由经理或客户端和请求使用NOLOCK提示一段时间没有对此接受的理由。

实体框架6,你可以实现自己的DbCommandInterceptor这样的:

有了这个类的地方,就可以用它在应用程序启动:

DbInterception.Add(new NoLockInterceptor()); 

并有条件地关闭加入NOLOCK提示当前线程的查询:

NoLockInterceptor.SuppressNoLock = true; 
9

加强对Doctor Jones的接受答案并使用PostSharp;

第一“ReadUncommitedTransactionScopeAttribute

[Serializable] 
public class ReadUncommitedTransactionScopeAttribute : MethodInterceptionAspect 
{ 
    public override void OnInvoke(MethodInterceptionArgs args) 
    { 
     //declare the transaction options 
     var transactionOptions = new TransactionOptions(); 
     //set it to read uncommited 
     transactionOptions.IsolationLevel = IsolationLevel.ReadUncommitted; 
     //create the transaction scope, passing our options in 
     using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions)) 
     { 
      //declare our context 
      using (var scope = new TransactionScope()) 
      { 
       args.Proceed(); 
       scope.Complete(); 
      } 
     } 
    } 
} 

然后,每当你需要它,

[ReadUncommitedTransactionScope()] 
    public static SomeEntities[] GetSomeEntities() 
    { 
     using (var context = new MyEntityConnection()) 
     { 
      //any reads we do here will also read uncomitted data 
      //... 
      //... 

     } 
    } 

能够加上“NOLOCK”与拦截器也不错,但连接到时将无法正常工作其他数据库系统如Oracle等。

0

一个选择是使用存储过程(类似于Ryan提出的视图解决方案),然后从EF执行存储过程。这样,存储过程执行脏读,而EF只是管理结果。