Non, mais vous pouvez démarrer une transaction et définir le niveau d'isolation sur lecture non validée . 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 le cadre de la transaction.
Si cela ressemble à ce que vous voulez, voici comment procéder ...
//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 rendre cela plus facile
la source
Si vous avez besoin de quelque chose en général, la meilleure façon dont nous avons trouvé qui est moins intrusif que de démarrer réellement une transactioncope à chaque fois, est de simplement définir le niveau d'isolation de transaction par défaut sur votre connexion après avoir créé votre contexte d'objet en exécutant cette simple commande:
http://msdn.microsoft.com/en-us/library/aa259216(v=sql.80).aspx
Avec cette technique, nous avons pu créer un fournisseur EF simple qui crée le contexte pour nous et exécute réellement cette commande à chaque fois pour l'ensemble de notre contexte afin que nous soyons toujours en «lecture non validée» par défaut.
la source
Transactions running at the READ UNCOMMITTED level do not issue shared locks
. Cela implique que vous devez exécuter une transaction pour en tirer profit. (extrait de msdn.microsoft.com/en-gb/library/ms173763.aspx ). Votre approche est peut-être moins intrusive, mais elle n'apportera rien si vous n'utilisez pas de transaction.SET TRANSACTION ISOLATION LEVEL...
commande affecte une propriété au niveau de la connexion et par conséquent affecte toutes les instructions SQL effectuées à partir de ce point (pour CETTE connexion), sauf si elle est remplacée par une indication de requête. Ce comportement existe depuis au moins SQL Server 2000 et probablement avant.CREATE TABLE ##Test(Col1 INT); BEGIN TRAN; SELECT * FROM ##Test WITH (TABLOCK, XLOCK);
. Ouvrez une autre requête (n ° 2) et exécutez:SELECT * FROM ##Test;
. Le SELECT ne reviendra pas car il est bloqué par la transaction toujours ouverte dans l'onglet n ° 1 qui utilise un verrou exclusif. Annulez le SELECT dans # 2. ExécutezSET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
une fois dans l'onglet # 2. Exécutez juste le SELECT à nouveau dans l'onglet # 2 et il reviendra. Assurez-vous d'exécuterROLLBACK
dans l'onglet # 1.Bien que je sois tout à fait d'accord pour dire que l'utilisation du niveau d'isolation de transaction Read Uncommitted est le meilleur choix, mais vous avez parfois été obligé d'utiliser l'indication NOLOCK à la demande du gestionnaire ou du client et aucune raison ne l'a acceptée.
Avec Entity Framework 6, vous pouvez implémenter votre propre DbCommandInterceptor comme ceci:
Avec cette classe en place, vous pouvez l'appliquer au démarrage de l'application:
Et désactivez conditionnellement l'ajout d'
NOLOCK
indices dans les requêtes pour le thread actuel:la source
public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) { if (!SuppressNoLock) command.CommandText = $"SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;{Environment.NewLine}{command.CommandText}"; base.ReaderExecuting(command, interceptionContext); }
Amélioration de la réponse acceptée par le docteur Jones et utilisation de PostSharp ;
Premier " ReadUncommitedTransactionScopeAttribute "
Puis chaque fois que vous en avez besoin,
Être capable d'ajouter "NOLOCK" avec un intercepteur est également agréable mais ne fonctionnera pas lors de la connexion à d'autres systèmes de base de données comme Oracle en tant que tel.
la source
Pour contourner cela, je crée une vue sur la base de données et j'applique NOLOCK sur la requête de la vue. Je traite ensuite la vue comme une table dans EF.
la source
Avec l'introduction d'EF6, Microsoft recommande d'utiliser la méthode BeginTransaction ().
Vous pouvez utiliser BeginTransaction au lieu de TransactionScope dans EF6 + et EF Core
la source
Non, pas vraiment - Entity Framework est fondamentalement une couche assez stricte au-dessus de votre base de données réelle. Vos requêtes sont formulées dans ESQL - Entity SQL - qui est tout d'abord ciblé vers votre modèle d'entité, et comme EF prend en charge plusieurs backends de base de données, vous ne pouvez pas vraiment envoyer du SQL "natif" directement à votre backend.
L'indicateur de requête NOLOCK est une chose spécifique à SQL Server et ne fonctionnera sur aucune des autres bases de données prises en charge (à moins qu'elles aient également implémenté le même indice - ce dont je doute fortement).
Marc
la source
Database.ExecuteSqlCommand()
ouDbSet<T>.SqlQuery()
.(NOLOCK)
toute façon - voir Bad Habits to kick - mettre NOLOCK partout - il n'est PAS RECOMMANDÉ de l'utiliser partout - bien au contraire!Une option consiste à utiliser une procédure stockée (similaire à la solution d'affichage proposée par Ryan), puis à exécuter la procédure stockée à partir d'EF. De cette façon, la procédure stockée effectue la lecture incorrecte tandis que EF canalise uniquement les résultats.
la source