如何强制Linq生成带有WITH(NOLOCK)语句的SQL查询
让Linq生成带WITH(NOLOCK)的SQL语句
你遇到的问题是用TransactionScope设置ReadUncommitted隔离级别后,Linq生成的SQL没有显式出现WITH(NOLOCK)关键字。以下是几种解决方法:
1. 理解隔离级别与NOLOCK的等效性
首先要明确:SQL Server中READ UNCOMMITTED隔离级别和表级的WITH(NOLOCK)提示效果完全一致——都允许读取未提交的数据。你当前的代码已经让查询在READ UNCOMMITTED级别执行,只是Linq不会将隔离级别转化为显式的WITH(NOLOCK)写在SQL里。如果只是需要读未提交的业务效果,现有代码已经生效,无需额外操作。
2. 手动编写带NOLOCK的SQL(直接高效)
如果一定要让生成的SQL显式包含WITH(NOLOCK),可以直接使用ORM的原生SQL执行方法:
针对LINQ to SQL:
using (var db = new YourDataContext()) { var agents = db.ExecuteQuery<TBLAgent>( "SELECT * FROM TBLAgent WITH(NOLOCK) WHERE AgentID != {0}", 2 ); agents.Dump(); }
针对Entity Framework Core:
using (var db = new YourDbContext()) { var agents = db.TBLAgents.FromSqlRaw( "SELECT * FROM TBLAgent WITH(NOLOCK) WHERE AgentID != {0}", 2 ).ToList(); agents.Dump(); }
3. 扩展方法统一添加NOLOCK提示
可以封装扩展方法,给IQueryable添加WithNoLock能力,避免重复写原生SQL:
public static class QueryableExtensions { public static IQueryable<T> WithNoLock<T>(this IQueryable<T> query) { // 针对LINQ to SQL,获取DataContext并设置隔离级别 var dataContext = query.GetType().GetProperty("Context")?.GetValue(query, null) as DataContext; dataContext?.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"); return query; } } // 使用方式: using (var transactionScope = new TransactionScope( TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted } )) { var x = from b in TBLAgents.WithNoLock() where b.AgentID != 2 select b; x.Dump(); transactionScope.Complete(); }
内容的提问来源于stack exchange,提问作者Abolfazl Pourmohammad
相关产品推荐
相关产品推荐

