2009-08-03 65 views
61

Có thể để Linq2Sql phát ra một NOLOCK trong SQL của nó không? Và nếu vậy, làm thế nào?NOLOCK với LINQ to SQL

+0

Chỉ tìm thấy câu hỏi này mà vượt qua một phần, nhưng vẫn do đó: http://stackoverflow.com/questions/62963/how-do-you-extend-linq-to-sql Tôi sẽ giữ câu hỏi mở trong một thời gian chỉ trong trường hợp. –

Trả lời

77

Có nó được, vì vậy đây là sự xâm nhập from my blog:

Các gợi ý NOLOCK chủ yếu là giống như gói một truy vấn trong một giao dịch mà "cô lập mức" là thiết lập để "đọc không bị giam". Nó có nghĩa là rằng truy vấn không quan tâm nếu nội dung đang được ghi vào các hàng mà nó đang đọc - nó sẽ đọc dữ liệu "bẩn" và trả lại như một phần của tập hợp kết quả.

Chỉ ra rằng bạn có thể thực hiện toàn bộ giao dịch "đọc không được cam kết" bằng cách sử dụng không gian tên System.Transactions cũ được giới thiệu trong .NET 2.0. Dưới đây là một số mẫu mã:

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

Vì vậy, tôi tạo ra một đối tượng TransactionScope mới và nói cho nó để sử dụng một đọc không bị giam mức cô lập. Truy vấn trong câu lệnh "đang sử dụng" bây giờ hoạt động như thể tất cả các bảng của nó đang đọc với gợi ý NOLOCK.

Dưới đây là kết quả đầu tiên từ một tìm kiếm Google cho "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 ...

+6

Nếu tôi muốn hoàn toàn chính xác, không có tùy chọn nào trong số này thực sự "phát ra NOLOCK" trong chính SQL - chúng sử dụng cài đặt cách ly của giao dịch thay thế. Tương tự, nhưng về mặt kỹ thuật thì câu hỏi được đặt ra là gì. –

+3

Sao chép văn bản từ blog của bạn để không ai phải nhấp qua liên kết để nhận được câu trả lời. – Eric

+1

Không phải lo lắng. Điểm chính của tôi là công cụ này có thể dễ dàng khám phá trên Google mà không phải hỏi ở đây. Câu hỏi này có thể sẽ chiếm đoạt vị trí số 1 trên Google cho tìm kiếm này ngay bây giờ. :) –

7

Dưới đây là một phương pháp mở rộng để sử dụng với 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(); 
    } 
} 

Sau đó, bạn có thể gọi nó như:

MyTable.Where(t => t.Title = "Blah").Dump2(); 
+2

Đây là một thực sự tốt đẹp dung dịch. Sạch sẽ và đơn giản! – Colin

10

Một cách đơn giản có thể để chạy một lệnh trên lớp DataContext của bạn

using (var dataContext = new DataContext()) 
{ 
    dataContext.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"); 

    // Your SQL query 
} 
+0

Có lẽ câu trả lời này được nhúng với câu trả lời theKings sẽ là một điều tốt đẹp để có – Pierre

2

Trong trường hợp của tôi, Entity Framework 5 (dựa trên câu trả lời @Soppus):

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

Cảm ơn, giải pháp của bạn tránh được "COMException: Trình quản lý giao dịch đã vô hiệu hóa hỗ trợ cho các giao dịch từ xa/mạng." có thể phụ thêm vào các yêu cầu khác. –

15

tiếp tục để theking của 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); 
    } 
} 

Điều cuối cùng có nghĩa là bạn có thể thực hiện NOLOCK đối với bất kỳ truy vấn đánh giá nào mà bạn chưa viết số NoLock (như tôi đã có cho số ToListNoLock ở trên). Vì vậy, ví dụ:

somequery.NoLock((x)=>x.Count()).Dump(); 

sẽ đánh giá truy vấn với NOLOCK.

Lưu ý rằng bạn phải đảm bảo bạn đang đánh giá truy vấn. Ví dụ. .NoLock((x)=>x.Distinct()).Count().Dump() sẽ không làm bất cứ điều gì hữu ích khác với .Distinct().Count().Dump().

+1

Điều này có thể được dọn dẹp một chút bằng cách thêm phương thức 'GetReadUncommittedScope()' tĩnh và sau đó thực hiện 'using (var txn = GetReadUncommittedScope())' – asherber

+0

@asherber Xong. –