entity framework与NOLOCK

我如何在entity framework上使用NOLOCK函数? XML是唯一的方法来做到这一点?

不,但是您可以启动事务并将隔离级别设置为未读取 。 这和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(); } 

扩展方法可以使这更容易

 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; } } 

如果您需要大量的东西,我们发现每次都要比实际启动一个事务处理器更less干扰的最好方法是在通过运行以下简单命令创build对象上下文之后,简单地在连接上设置默认的事务隔离级别:

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

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

使用这种技术,我们可以创build一个简单的EF提供程序,为我们创build上下文,并且每次都为我们的上下文实际运行此命令,以便默认情况下始终处于“未提交读取”状态。

虽然我完全同意使用Read Uncommitted事务隔离级别是最好的select,但是有时候你被pipe理员或者客户端的请求强迫使用NOLOCK提示,并且没有理由接受。

使用Entity Framework 6,您可以像这样实现自己的DbCommandInterceptor:

 public class NoLockInterceptor : DbCommandInterceptor { private static readonly Regex _tableAliasRegex = new Regex(@"(?<tableAlias>AS \[Extent\d+\](?! WITH \(NOLOCK\)))", RegexOptions.Multiline | RegexOptions.IgnoreCase); [ThreadStatic] public static bool SuppressNoLock; public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { if (!SuppressNoLock) { command.CommandText = _tableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)"); } } public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) { if (!SuppressNoLock) { command.CommandText = _tableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)"); } } } 

有了这个课程,您可以在申请开始时使用它:

 DbInterception.Add(new NoLockInterceptor()); 

并有条件地closures当前线程的查询添加NOLOCK提示:

 NoLockInterceptor.SuppressNoLock = true; 

加强琼斯博士接受的答案并使用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)时不起作用。

为了解决这个问题,我在数据库上创build一个视图并在视图的查询上应用NOLOCK。 然后,我把这个视图看作EF中的一个表格。

不,不是真的 – entity framework基本上是一个相当严格的图层上方的实际数据库。 您的查询是在ESQL – Entity SQL中制定的 – 首先是针对您的实体模型,由于EF支持多个数据库后端,因此您无法直接将“本地”SQL发送到您的后端。

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

渣子

一种select是使用存储过程(类似于Ryan提出的视图解决scheme),然后从EF执行存储过程。 这样,存储过程执行脏读,而EF只是pipe理结果。