Comment utiliser la fonction NOLOCK sur Entity Framework? XML est-il le seul moyen de faire cela?
Réponses
Trop de publicités?Non, mais vous pouvez lancer une transaction et définir le niveau d'isolement à lire non validé . Cela fait essentiellement la même chose que NOLOCK, mais au lieu de le faire par table, il le fera pour tout ce qui est dans la portée de la transaction.
Si cela ressemble à ce que vous voulez, voici comment vous pouvez le faire ...
//declare the transaction options
var transactionOptions = new System.Transactions.TransactionOptions();
//set it to read uncommited
transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted;
//create the transaction scope, passing our options in
using (var transactionScope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required, transactionOptions))
//declare our context
using (var context = new MyEntityConnection())
{
//any reads we do here will also read uncomitted data
//...
//...
//don't forget to complete the transaction scope
transactionScope.Complete();
}
Les méthodes d'extension peuvent faciliter cela
public static List<T> ToListReadUncommitted<T>(this IQueryable<T> query)
{
using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
{
List<T> toReturn = query.ToList();
scope.Complete();
return toReturn;
}
}
public static int CountReadUncommitted<T>(this IQueryable<T> query)
{
using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
{
int toReturn = query.Count();
scope.Complete();
return toReturn;
}
}
Si vous avez besoin de quelque chose de grand, le meilleur moyen que nous avons trouvé moins intrusive que le commencement d'une transactionscope à chaque fois, c'est simplement de définir la valeur par défaut niveau d'isolation de transaction sur votre connexion une fois que vous avez créé votre contexte de l'objet par l'exécution de cette commande simple:
this.context.ExecuteStoreCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
http://msdn.microsoft.com/en-us/library/aa259216(v=sql.80).aspx
Avec cette technique, nous avons été en mesure de créer un simple EF fournisseur qui crée le cadre pour nous et exécute cette commande à chaque fois pour toutes de notre contexte, de sorte que nous sommes toujours en "read uncommitted" par défaut.
Même si je suis absolument d'accord que l'utilisation de Read Uncommitted niveau d'isolation de transaction est le meilleur choix, mais un certain temps vous a forcé à utiliser NOLOCK information à la demande du gestionnaire ou d'un client et pas de raisons contre cette acceptée.
Avec Entity Framework 6 vous pouvez mettre en œuvre leurs propres DbCommandInterceptor comme ceci:
public class NoLockInterceptor : DbCommandInterceptor
{
private static readonly Regex _tableAliasRegex =
new Regex(@"(?<tableAlias>AS \[Extent\d+\](?! WITH \(NOLOCK\)))",
RegexOptions.Multiline | RegexOptions.IgnoreCase);
[ThreadStatic]
public static bool SuppressNoLock;
public override void ScalarExecuting(DbCommand command,
DbCommandInterceptionContext<object> interceptionContext)
{
if (!SuppressNoLock)
{
command.CommandText =
_tableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)");
}
}
public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
if (!SuppressNoLock)
{
command.CommandText =
_tableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)");
}
}
}
Avec cette classe, vous pouvez l'appliquer sur démarrage de l'application:
DbInterception.Add(new NoLockInterceptor());
Et à condition de désactiver l'ajout de NOLOCK
de l'indice dans les requêtes pour le thread courant:
NoLockInterceptor.SuppressNoLock = true;