Is it possible to get Linq2Sql to emit a NOLOCK in its SQL? And if so, how?
-
Just found this question which crosses over in part, but credit due anyway: http://stackoverflow.com/questions/62963/how-do-you-extend-linq-to-sql I'll keep the question open for a while just in case. – Scott McKenzie Aug 03 '09 at 05:50
5 Answers
Yes it is, so here's the entry from my blog:
The NOLOCK hint is essentially the same as wrapping a query in a transaction whose "isolation level" is set to "read uncommitted". It means that the query doesn't care if stuff is in the process of being written to the rows it's reading from - it'll read that "dirty" data and return it as part of the result set.
Turns out that you can do the whole "read uncommitted" transaction thing using the old System.Transactions namespace introduced in .NET 2.0. Here's some sample code:
using (var txn = new TransactionScope( TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted } )) { // Your LINQ to SQL query goes here }
So I'm creating a new TransactionScope object and telling it to use a read-uncommitted isolation level. The query within the "using" statement now acts as if all its tables were reading with the NOLOCK hint.
Here are the first results from a Google search for "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 ...

- 92,005
- 12
- 114
- 115

- 200,371
- 61
- 386
- 320
-
6If I wanted to be totally correct, none of these options actually "emit a NOLOCK" in the SQL itself - they use the transaction's isolation setting instead. Same thing, but not technically what the question asked. – Matt Hamilton Aug 03 '09 at 05:56
-
3Copied the text from your blog, so that nobody has to click-through links to get to the answer. – Eric Aug 03 '09 at 06:06
-
1No worries. My main point was that this stuff is easily discoverable on Google without having to ask here. This question will probably usurp the #1 place on Google for this search now. :) – Matt Hamilton Aug 03 '09 at 06:18
-
2@Matt: That's the point! Create a canonical source! See: http://meta.stackexchange.com/questions/8724/how-to-deal-with-google-questions/8729#8729 – Eric Aug 03 '09 at 06:21
-
Yeah I dunno if I wholly agree with that idea. For me, Scott's or my blog post was the canonical source for that answer. I don't know if my stealing content from others' blogs (or even mine) is the right approach. – Matt Hamilton Aug 03 '09 at 08:23
-
7Would have to aggree with Matt on the content stealing. Matt took the time to write the post on his blog. Now SOF is getting the traffic – Andrew Harry Dec 18 '09 at 14:36
-
5You can't upvote and downvote answers on a blog and so there is no way to vet the quality over there. I think copying short snippets to SO with attribution is the right way to go. – Kirk Woll Jun 21 '11 at 15:20
-
Well, the real answer is that you cannot use nolock hint with linqtosql. Hanselman alos wrote about this: http://www.hanselman.com/blog/GettingLINQToSQLAndLINQToEntitiesToUseNOLOCK.aspx – gerleim Sep 07 '11 at 22:33
-
Is there any reason to keep a reference to the variable `txn`? Do you have to pass the reference to your context? – Drew Noakes Jan 13 '12 at 12:17
-
@Drew Good point. I don't believe there is any need for the `txn` variable. Been a long time since I've played with this stuff - it'd be worth testing yourself. – Matt Hamilton Jan 13 '12 at 22:45
-
Ahhhh... performance relief. To what address do a send the pizza's and t-shirts? – Pete M May 09 '12 at 18:04
-
In my case, TransactionScope has raise some COMException: https://stackoverflow.com/questions/10130767/the-transaction-manager-has-disabled-its-support-for-remote-network-transactions – Olivier de Rivoyre Jun 27 '17 at 08:13
-
You omitted the `txn.Complete();`. Was that on purpose? I see that it works without it, but I'm told it's needed. Perhaps you can answer my question [Do I need “transactionScope.Complete();”?](https://stackoverflow.com/q/53657509/939213). – ispiro Dec 06 '18 at 19:10
Further to theKing's 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);
}
}
The last one means you can do a NOLOCK
on any evaluating queries you haven't a NoLock
explicitly written for (like I've got for ToListNoLock
above). So, for example:
somequery.NoLock((x)=>x.Count()).Dump();
will evaluate the query with NOLOCK
.
Note that you have to ensure you're evaluating the query. E.g. .NoLock((x)=>x.Distinct()).Count().Dump()
won't do anything usefully different from .Distinct().Count().Dump()
.
A simple way may be to run a command on your DataContext class
using (var dataContext = new DataContext())
{
dataContext.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
// Your SQL query
}

- 502
- 2
- 6
- 17
Here is an extension method to use with 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();
}
}
Then you can call it as:
MyTable.Where(t => t.Title = "Blah").Dump2();

- 1,616
- 4
- 18
- 23
In my case, Entity Framework 5 (based on @Soppus answer):
private FoobarEntities db = new FoobarEntities();
public FoobarController()
{
db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
}

- 4,685
- 4
- 42
- 43
-
1Thanks, your solution avoid the "COMException: The transaction manager has disabled its support for remote/network transactions." that may append on other requests. – Olivier de Rivoyre Jun 27 '17 at 08:16