Entity Framework avec NOLOCK

Comment utiliser la fonction NOLOCK sur Entity Framework? XML est-il le seul moyen de faire cela?

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 scope 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 ToListReadUncommitted(this IQueryable query) { using (var scope = new TransactionScope( TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted })) { List toReturn = query.ToList(); scope.Complete(); return toReturn; } } public static int CountReadUncommitted(this IQueryable 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 plus large, la meilleure façon de moins intrusive que de lancer une transaction à chaque fois est de définir le niveau d’isolement de transaction par défaut sur votre connexion après avoir créé ce contexte:

 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 fournisseur EF simple qui crée le contexte pour nous et exécute cette commande à chaque fois pour que nous soyons toujours “en lecture non validée” par défaut.

Bien que je sois tout à fait d’accord sur le fait que l’utilisation du niveau d’isolation des transactions Read Uncommitted est le meilleur choix, vous devez forcément utiliser l’indicateur NOLOCK à la demande du responsable ou du client, et rien n’empêche.

Avec Entity Framework 6, vous pouvez implémenter DbCommandInterceptor comme ceci:

 public class NoLockInterceptor : DbCommandInterceptor { private static readonly Regex _tableAliasRegex = new Regex(@"(?AS \[Extent\d+\](?! WITH \(NOLOCK\)))", RegexOptions.Multiline | RegexOptions.IgnoreCase); [ThreadStatic] public static bool SuppressNoLock; public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext interceptionContext) { if (!SuppressNoLock) { command.CommandText = _tableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)"); } } public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext interceptionContext) { if (!SuppressNoLock) { command.CommandText = _tableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)"); } } } 

Avec cette classe en place, vous pouvez l’appliquer au démarrage de l’application:

 DbInterception.Add(new NoLockInterceptor()); 

Et désactiver conditionnellement l’ajout de l’indicateur NOLOCK dans les requêtes pour le thread en cours:

 NoLockInterceptor.SuppressNoLock = true; 

Amélioration de la réponse acceptée du docteur Jones et utilisation de PostSharp ;

Premier ” ReadUncommitedTransactionScopeAtsortingbute

 [Serializable] public class ReadUncommitedTransactionScopeAtsortingbute : MethodInterceptionAspect { public override void OnInvoke(MethodInterceptionArgs args) { //declare the transaction options var transactionOptions = new TransactionOptions(); //set it to read uncommited transactionOptions.IsolationLevel = IsolationLevel.ReadUncommitted; //create the transaction scope, passing our options in using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions)) { //declare our context using (var scope = new TransactionScope()) { args.Proceed(); scope.Complete(); } } } } 

Alors, quand vous en avez besoin,

  [ReadUncommitedTransactionScope()] public static SomeEntities[] GetSomeEntities() { using (var context = new MyEntityConnection()) { //any reads we do here will also read uncomitted data //... //... } } 

Être capable d’append “NOLOCK” avec un intercepteur est également intéressant mais ne fonctionnera pas lors de la connexion à d’autres systèmes de firebase database comme Oracle en tant que tels.

Pour contourner ce problème, je crée une vue sur la firebase database et applique NOLOCK à la requête de la vue. Je traite ensuite la vue comme un tableau dans EF.

Non, pas vraiment – Entity Framework est essentiellement une couche assez ssortingcte au-dessus de votre firebase database réelle. Vos requêtes sont formulées dans ESQL – Entity SQL – qui cible tout d’abord votre modèle d’entité, et comme EF prend en charge plusieurs moteurs de firebase database, vous ne pouvez pas envoyer directement de SQL “natif” directement à votre backend.

L’indicateur de requête NOLOCK est spécifique à SQL Server et ne fonctionnera pas sur les autres bases de données sockets en charge (à moins qu’elles n’aient également implémenté le même indice, ce dont je doute fort).

Marc

Avec l’introduction de EF6, Microsoft recommande d’utiliser la méthode BeginTransaction ().

Vous pouvez utiliser BeginTransaction au lieu de TransactionScope dans EF6 + et EF Core

 using (var ctx = new ContractDbContext()) using (var transaction = ctx.Database.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted)) { //any reads we do here will also read uncommitted data } 

Une option consiste à utiliser une procédure stockée (similaire à la solution de visualisation proposée par Ryan), puis à exécuter la procédure stockée depuis EF. De cette façon, la procédure stockée exécute la lecture incorrecte alors que EF ne fait que canaliser les résultats.