【发布时间】:2009-08-03 05:46:59
【问题描述】:
是否可以让 Linq2Sql 在其 SQL 中发出 NOLOCK?如果有,怎么做?
【问题讨论】:
-
刚发现这个问题部分交叉,但无论如何都要归功于:stackoverflow.com/questions/62963/how-do-you-extend-linq-to-sql我会保持这个问题开放一段时间以防万一。
标签: linq-to-sql
是否可以让 Linq2Sql 在其 SQL 中发出 NOLOCK?如果有,怎么做?
【问题讨论】:
标签: linq-to-sql
是的,这是from my blog的条目:
NOLOCK 提示本质上是 与将查询包装在 “隔离级别”为的事务 设置为“读取未提交”。它的意思是 查询不关心内容 正在被写入 它正在读取的行 - 它会 读取“脏”数据并返回 作为结果集的一部分。
原来你可以做整个 “读取未提交”事务的东西 使用旧的 System.Transactions .NET 2.0 中引入的命名空间。 下面是一些示例代码:
using (var txn = new TransactionScope( TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted } )) { // Your LINQ to SQL query goes here }所以我正在创建一个新的 TransactionScope 对象并告诉它使用 读未提交的隔离级别。这 现在在“使用”语句中查询 就好像它的所有表格都在阅读 带有 NOLOCK 提示。
以下是 Google 搜索“linq sql nolock”的第一批结果:
InfoQ: Implementing NOLOCK with LINQ to SQL and LINQ to Entities
Matt Hamilton - LINQ to SQL and NOLOCK Hints : Mad Props!
Scott Hanselman's Computer Zen - Getting LINQ to SQL and LINQ to ...
【讨论】:
进一步的国王LinqPad My Extensions addition:
public static IQueryable<T> DumpNoLock<T>(this IQueryable<T> query)
{
using (var txn = GetNewReadUncommittedScope())
{
return query.Dump();
}
}
public static System.Transactions.TransactionScope GetNewReadUncommittedScope()
{
return new System.Transactions.TransactionScope(
System.Transactions.TransactionScopeOption.RequiresNew,
new System.Transactions.TransactionOptions
{
IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
});
}
public static IQueryable<T> DumpNoLock<T>(this IQueryable<T> query, string description)
{
using (var txn = GetNewReadUncommittedScope())
{
return query.Dump(description);
}
}
public static List<T> ToListNoLock<T>(this IQueryable<T> query)
{
using (var txn = GetNewReadUncommittedScope())
{
return query.ToList();
}
}
public static U NoLock<T,U>(this IQueryable<T> query, Func<IQueryable<T>,U> expr)
{
using (var txn = GetNewReadUncommittedScope())
{
return expr(query);
}
}
最后一个意味着您可以对任何没有明确编写NoLock 的评估查询执行NOLOCK(就像上面的ToListNoLock 一样)。所以,例如:
somequery.NoLock((x)=>x.Count()).Dump();
将使用NOLOCK 评估查询。
请注意,您必须确保您正在评估查询。例如。 .NoLock((x)=>x.Distinct()).Count().Dump() 不会做任何与 .Distinct().Count().Dump() 不同的有用的事情。
【讨论】:
一种简单的方法可能是在 DataContext 类上运行命令
using (var dataContext = new DataContext())
{
dataContext.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
// Your SQL query
}
【讨论】:
这是与 LINQPAD 一起使用的扩展方法
public static IQueryable<T> Dump2<T>(this IQueryable<T> query)
{
using (var txn = new System.Transactions.TransactionScope(TransactionScopeOption.RequiresNew,
new TransactionOptions
{
IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
}))
{
return query.Dump();
}
}
那么你可以这样称呼它:
MyTable.Where(t => t.Title = "Blah").Dump2();
【讨论】:
就我而言,Entity Framework 5(基于@Soppus 的回答):
private FoobarEntities db = new FoobarEntities();
public FoobarController()
{
db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
}
【讨论】: