Nein, aber Sie können eine Transaktion starten und die Isolationsstufe so einstellen , dass sie nicht festgeschrieben wird . Dies macht im Wesentlichen dasselbe wie NOLOCK, aber anstatt es pro Tabelle zu tun, wird es für alles im Rahmen der Transaktion getan.
Wenn das so klingt, wie Sie es möchten, können Sie es folgendermaßen tun ...
//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();
}
Erweiterungsmethoden können dies erleichtern
quelle
Wenn Sie etwas im Allgemeinen benötigen, ist es am besten, die Standardtransaktionsisolationsstufe für Ihre Verbindung festzulegen, nachdem Sie Ihren Objektkontext erstellt haben, indem Sie diesen einfachen Befehl ausführen:
http://msdn.microsoft.com/en-us/library/aa259216(v=sql.80).aspx
Mit dieser Technik konnten wir einen einfachen EF-Anbieter erstellen, der den Kontext für uns erstellt und diesen Befehl jedes Mal für den gesamten Kontext ausführt, sodass wir standardmäßig immer "nicht festgeschrieben" lesen.
quelle
Transactions running at the READ UNCOMMITTED level do not issue shared locks
. Dies bedeutet, dass Sie innerhalb einer Transaktion ausgeführt werden müssen, um den Vorteil zu erhalten. (entnommen aus msdn.microsoft.com/en-gb/library/ms173763.aspx ). Ihr Ansatz ist zwar weniger aufdringlich, bringt jedoch nichts, wenn Sie keine Transaktion verwenden.SET TRANSACTION ISOLATION LEVEL...
Befehl wirkt sich auf eine Eigenschaft auf Verbindungsebene aus und wirkt sich daher auf alle SQL-Anweisungen aus, die ab diesem Zeitpunkt (für DIESE Verbindung) ausgeführt werden, sofern sie nicht durch einen Abfragehinweis überschrieben werden. Dieses Verhalten gibt es seit mindestens SQL Server 2000 und wahrscheinlich schon früher.CREATE TABLE ##Test(Col1 INT); BEGIN TRAN; SELECT * FROM ##Test WITH (TABLOCK, XLOCK);
. Öffnen Sie eine andere Abfrage (Nr. 2) und führen Sie Folgendes aus :SELECT * FROM ##Test;
. Das SELECT wird nicht zurückgegeben, da es durch die noch geöffnete Transaktion in Registerkarte 1 blockiert wird, die eine exklusive Sperre verwendet. Brechen Sie die AUSWAHL in # 2 ab. Führen SieSET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
einmal in Tab. 2 aus. Führen Sie nur SELECT erneut in Tab. 2 aus, und es wird wieder angezeigt. Stellen Sie sicher, dass SieROLLBACK
in Registerkarte 1 ausgeführt werden.Ich stimmte zwar absolut zu, dass die Verwendung der Isolationsstufe für nicht festgeschriebene Transaktionen die beste Wahl ist, aber einige Zeit haben Sie gezwungen, den NOLOCK-Hinweis auf Anfrage des Managers oder Kunden zu verwenden, und es wurden keine Gründe dafür akzeptiert.
Mit Entity Framework 6 können Sie Ihren eigenen DbCommandInterceptor wie folgt implementieren:
Mit dieser Klasse können Sie sie beim Start der Anwendung anwenden:
Deaktivieren Sie unter bestimmten Bedingungen das Hinzufügen von
NOLOCK
Hinweisen zu Abfragen für den aktuellen Thread:quelle
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); }
Verbesserung der akzeptierten Antwort von Doktor Jones und Verwendung von PostSharp ;
Zuerst " ReadUncommitedTransactionScopeAttribute "
Dann, wann immer Sie es brauchen,
Die Möglichkeit, "NOLOCK" mit einem Interceptor hinzuzufügen, ist ebenfalls hilfreich, funktioniert jedoch nicht, wenn eine Verbindung zu anderen Datenbanksystemen wie Oracle als solches hergestellt wird.
quelle
Um dies zu umgehen, erstelle ich eine Ansicht in der Datenbank und wende NOLOCK auf die Abfrage der Ansicht an. Ich behandle die Ansicht dann als Tabelle in EF.
quelle
Mit der Einführung von EF6 empfiehlt Microsoft die Verwendung der BeginTransaction () -Methode.
Sie können BeginTransaction anstelle von TransactionScope in EF6 + und EF Core verwenden
quelle
Nein, nicht wirklich - Entity Framework ist im Grunde eine ziemlich strenge Schicht über Ihrer eigentlichen Datenbank. Ihre Abfragen werden in ESQL - Entity SQL - formuliert, das in erster Linie auf Ihr Entitätsmodell ausgerichtet ist. Da EF mehrere Datenbank-Backends unterstützt, können Sie "natives" SQL nicht direkt an Ihr Backend senden.
Der NOLOCK-Abfragehinweis ist eine SQL Server-spezifische Sache und funktioniert in keiner der anderen unterstützten Datenbanken (es sei denn, sie haben denselben Hinweis ebenfalls implementiert - was ich stark bezweifle).
Marc
quelle
Database.ExecuteSqlCommand()
oder ausführenDbSet<T>.SqlQuery()
.(NOLOCK)
- siehe Bad Habits to kick - NOLOCK überall einsetzen - es wird NICHT EMPFOHLEN , dies überall zu verwenden - ganz im Gegenteil!Eine Möglichkeit besteht darin, eine gespeicherte Prozedur zu verwenden (ähnlich der von Ryan vorgeschlagenen Ansichtslösung) und dann die gespeicherte Prozedur von EF auszuführen. Auf diese Weise führt die gespeicherte Prozedur den Dirty Read durch, während EF nur die Ergebnisse weiterleitet.
quelle