linq to sql - usando - NOLOCK con Linq a SQL
usando linq to sql (5)
¿Es posible hacer que Linq2Sql emita un NOLOCK en su SQL? Y si es así, ¿cómo?
Además de la adición LinqPad My Extensions
del King :
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);
}
}
El último significa que puede hacer un NOLOCK
en cualquier consulta de evaluación para la que no NoLock
escrito explícitamente un NoLock
(como lo hice con ToListNoLock
arriba). Así por ejemplo:
somequery.NoLock((x)=>x.Count()).Dump();
evaluará la consulta con NOLOCK
.
Tenga en cuenta que debe asegurarse de que está evaluando la consulta. Por ejemplo, .NoLock((x)=>x.Distinct()).Count().Dump()
no hará nada útilmente diferente de .Distinct().Count().Dump()
.
Aquí hay un método de extensión para usar con 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();
}
}
Entonces puedes llamarlo así:
MyTable.Where(t => t.Title = "Blah").Dump2();
En mi caso, Entity Framework 5 (basado en @Soppus answer):
private FoobarEntities db = new FoobarEntities();
public FoobarController()
{
db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
}
Sí, lo es, así que aquí está la entrada de mi blog :
La sugerencia de NOLOCK es esencialmente lo mismo que envolver una consulta en una transacción cuyo "nivel de aislamiento" está configurado como "leído no confirmado". Significa que a la consulta no le importa si las cosas están en proceso de escribirse en las filas de las que está leyendo: leerá los datos "sucios" y los devolverá como parte del conjunto de resultados.
Resulta que puede hacer todo el asunto de la transacción "no confirmada" utilizando el antiguo espacio de nombres System.Transactions introducido en .NET 2.0. Aquí hay un código de muestra:
using (var txn = new TransactionScope( TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted } )) { // Your LINQ to SQL query goes here }
Así que estoy creando un nuevo objeto TransactionScope y diciéndole que use un nivel de aislamiento sin lectura. La consulta dentro de la instrucción "using" ahora actúa como si todas sus tablas estuvieran leyendo con la sugerencia de NOLOCK.
Estos son los primeros resultados de una búsqueda en Google para "nichock sqq sql":
InfoQ: implementación de NOLOCK con LINQ to SQL y LINQ a entidades
Matt Hamilton - LINQ to SQL y NOLOCK Sugerencias: ¡Mad Props!
Computer Zen de Scott Hanselman: obtener LINQ to SQL y LINQ para ...
Una forma simple puede ser ejecutar un comando en su clase DataContext
using (var dataContext = new DataContext())
{
dataContext.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
// Your SQL query
}