NOLOCK с Linq to SQL


можно ли заставить Linq2Sql выдавать NOLOCK в своем SQL? И если да, то как?

5 62

5 ответов:

да, так что вот запись из моего блога:

подсказка NOLOCK по существу так же, как оборачивать запрос в транзакция, чей "уровень изоляции" является установите значение "read uncommitted". Это значит что запрос не волнует, если вещи находится в процессе написания строки, из которых он читает - это будет прочитайте эти "грязные" данные и верните их как часть результирующего набора.

оказывается, что вы можете сделать все "читать незафиксированная " транзакционная вещь используя старую систему.Операции пространства имен, представленных в .Объем 2.0. Вот пример кода:

using (var txn = new TransactionScope(
    TransactionScopeOption.Required, 
    new TransactionOptions
    {
        IsolationLevel = IsolationLevel.ReadUncommitted
    }
))
{
    // Your LINQ to SQL query goes here
}

таким образом, я создаю новый объект transactionscope объект и говорит ему использовать чтение-незафиксированный уровень изоляции. Этот запрос в операторе "using" теперь действует так, как будто все его таблицы читают с намеком на НОЛОКА.

вот первые результаты поиска Google для " linq sql подсказку nolock":

InfoQ: реализация NOLOCK с LINQ to SQL и LINQ to Entities

Matt Hamilton-LINQ to SQL и Nolock подсказки: Безумный реквизит!

Скотта Хансельмана компьютер Дзен - получение LINQ к SQL и LINQ для ...

дальше к королю LinqPad My Extensions дополнение:

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