【问题标题】:NOLOCK with Linq to SQL使用 Linq to SQL 的 NOLOCK
【发布时间】:2009-08-03 05:46:59
【问题描述】:

是否可以让 Linq2Sql 在其 SQL 中发出 NOLOCK?如果有,怎么做?

【问题讨论】:

标签: linq-to-sql


【解决方案1】:

是的,这是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 ...

【讨论】:

  • 如果我想完全正确,这些选项实际上都没有在 SQL 本身中“发出 NOLOCK”——它们使用事务的隔离设置。同样的事情,但在技术上不是问题所问的。
  • 复制了您博客中的文字,因此没有人需要点击链接才能获得答案。
  • @Matt:这就是重点!创建一个规范的来源!见:meta.stackexchange.com/questions/8724/…
  • 必须同意马特关于内容窃取的意见。马特花时间在他的博客上写了这篇文章。现在 SOF 正在获得流量
  • 您不能在博客上对答案投赞成票和反对票,因此无法审查那里的质量。我认为将简短的 sn-ps 复制到 SO 并注明出处是正确的方法。
【解决方案2】:

进一步的国王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)=&gt;x.Distinct()).Count().Dump() 不会做任何与 .Distinct().Count().Dump() 不同的有用的事情。

【讨论】:

    【解决方案3】:

    一种简单的方法可能是在 DataContext 类上运行命令

    using (var dataContext = new DataContext())
    {
      dataContext.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
    
      // Your SQL query
    }
    

    【讨论】:

    • 也许这个嵌入 theKings 答案的答案会很不错
    【解决方案4】:

    这是与 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();
    

    【讨论】:

      【解决方案5】:

      就我而言,Entity Framework 5(基于@Soppus 的回答):

      private FoobarEntities db = new FoobarEntities();
      public FoobarController()
      {
          db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
      }
      

      【讨论】:

      • 谢谢,您的解决方案避免了“COMException:事务管理器已禁用对远程/网络事务的支持。”可能会附加在其他请求上。
      猜你喜欢
      • 2011-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-09
      • 1970-01-01
      • 2010-10-27
      相关资源
      最近更新 更多