मैं NOLOCK
एंटिटी फ्रेमवर्क पर फ़ंक्शन का उपयोग कैसे कर सकता हूं ? क्या XML ऐसा करने का एकमात्र तरीका है?
मैं NOLOCK
एंटिटी फ्रेमवर्क पर फ़ंक्शन का उपयोग कैसे कर सकता हूं ? क्या XML ऐसा करने का एकमात्र तरीका है?
जवाबों:
नहीं, लेकिन आप एक लेनदेन शुरू कर सकते हैं और बिना पढ़े अलगाव स्तर निर्धारित कर सकते हैं । यह अनिवार्य रूप से NOLOCK के समान है, लेकिन इसे प्रति तालिका के आधार पर करने के बजाय, यह लेनदेन के दायरे में सब कुछ के लिए करेगा।
यदि आपको लगता है कि आप क्या चाहते हैं, तो यहां बताया गया है कि आप इसे कैसे कर सकते हैं ...
//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();
}
एक्सटेंशन के तरीके इसे आसान बना सकते हैं
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;
}
}
यदि आपको बड़े पैमाने पर किसी चीज की आवश्यकता है, तो सबसे अच्छा तरीका जो हमने पाया है कि वास्तव में हर बार लेनदेन शुरू करने की तुलना में कम घुसपैठ है, बस इस साधारण कमांड को चलाकर अपनी वस्तु संदर्भ तैयार करने के बाद अपने कनेक्शन पर डिफ़ॉल्ट लेनदेन अलगाव स्तर निर्धारित करना है:
this.context.ExecuteStoreCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
http://msdn.microsoft.com/en-us/library/aa259216(v=sql.80).aspx
इस तकनीक के साथ, हम एक सरल ईएफ प्रदाता बनाने में सक्षम थे जो हमारे लिए संदर्भ बनाता है और वास्तव में हमारे संदर्भ के लिए हर बार इस कमांड को चलाता है ताकि हम हमेशा डिफ़ॉल्ट रूप से "अनक्मिटेड" पढ़ें।
Transactions running at the READ UNCOMMITTED level do not issue shared locks
। इसका तात्पर्य यह है कि लाभ पाने के लिए आपको लेनदेन के भीतर चलना चाहिए। ( msdn.microsoft.com/en-gb/library/ms173763.aspx से लिया गया )। आपका दृष्टिकोण कम घुसपैठ वाला हो सकता है, लेकिन यदि आप लेनदेन का उपयोग नहीं करते हैं तो यह कुछ भी हासिल नहीं करेगा।
SET TRANSACTION ISOLATION LEVEL...
आदेश एक कनेक्शन स्तरीय संपत्ति को प्रभावित करता है और जब तक एक प्रश्न संकेत द्वारा ओवरराइड इसलिए, सभी एसक्यूएल उस समय के बाद (उस कनेक्शन के लिए) से दिए गए बयान को प्रभावित करता है। यह व्यवहार कम से कम SQL Server 2000 के आसपास रहा है, और पहले भी संभव है।
CREATE TABLE ##Test(Col1 INT); BEGIN TRAN; SELECT * FROM ##Test WITH (TABLOCK, XLOCK);
:। एक और क्वेरी (# 2) खोलें और चलाएँ SELECT * FROM ##Test;
:। SELECT नहीं लौटेगा क्योंकि यह टैब # 1 में अभी भी खुले लेनदेन द्वारा अवरुद्ध किया जा रहा है जो एक विशेष लॉक का उपयोग कर रहा है। # 2 में चयन रद्द करें। SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
टैब # 2 में एक बार चलाएं । टैब # 2 में फिर से सिलेक्ट रन करें और यह वापस आ जाएगा। ROLLBACK
टैब # 1 में चलना सुनिश्चित करें ।
हालाँकि मैं इस बात से बिल्कुल सहमत था कि Read Uncommitted लेन-देन अलगाव स्तर का उपयोग करना सबसे अच्छा विकल्प है, लेकिन कुछ समय आपने प्रबंधक या क्लाइंट के अनुरोध पर NOLOCK संकेत का उपयोग करने के लिए मजबूर किया और इसके विरुद्ध कोई कारण स्वीकार नहीं किया गया।
एंटिटी फ्रेमवर्क 6 के साथ आप स्वयं DbCommandInterceptor को इस तरह लागू कर सकते हैं:
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)");
}
}
}
इस श्रेणी के साथ, आप इसे आवेदन शुरू होने पर लागू कर सकते हैं:
DbInterception.Add(new NoLockInterceptor());
और सशर्त रूप से NOLOCK
वर्तमान थ्रेड के लिए प्रश्नों में संकेत जोड़ना बंद करें :
NoLockInterceptor.SuppressNoLock = true;
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); }
पर बढ़ाना डॉक्टर जोन्स के स्वीकार किए जाते हैं जवाब और का उपयोग कर PostSharp ;
पहला " ReadUncommitedTransactionScopeAttribute "
[Serializable]
public class ReadUncommitedTransactionScopeAttribute : 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();
}
}
}
}
फिर जब भी आपको आवश्यकता हो,
[ReadUncommitedTransactionScope()]
public static SomeEntities[] GetSomeEntities()
{
using (var context = new MyEntityConnection())
{
//any reads we do here will also read uncomitted data
//...
//...
}
}
एक इंटरसेप्टर के साथ "NOLOCK" को जोड़ने में सक्षम होना भी अच्छा है, लेकिन Oracle जैसे अन्य डेटाबेस सिस्टम से कनेक्ट होने पर काम नहीं करेगा।
इसे प्राप्त करने के लिए मैं डेटाबेस पर एक दृश्य बनाता हूं और दृश्य की क्वेरी पर NOLOCK लागू करता हूं। मैं तो दृश्य को EF के भीतर एक तालिका के रूप में मानता हूं।
EF6 की शुरुआत के साथ, Microsoft BeginTransaction () विधि का उपयोग करने की सलाह देता है।
आप EF6 + और EF कोर में TransactionScope के बजाय BeginTransaction का उपयोग कर सकते हैं
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
}
नहीं, वास्तव में नहीं - एंटिटी फ्रेमवर्क मूल रूप से आपके वास्तविक डेटाबेस के ऊपर एक काफी सख्त परत है। ईएसक्यूएल - एंटिटी एसक्यूएल में आपके प्रश्नों को तैयार किया गया है - जो कि आपके इकाई मॉडल के लिए सबसे पहले लक्षित है, और चूंकि ईएफ कई डेटाबेस बैकेंड का समर्थन करता है, आप वास्तव में "देशी" एसक्यूएल को सीधे अपने बैकेंड पर नहीं भेज सकते हैं।
NOLOCK क्वेरी संकेत एक SQL सर्वर विशिष्ट बात है और किसी भी अन्य समर्थित डेटाबेस पर काम नहीं करेगा (जब तक कि उन्होंने भी वही संकेत लागू नहीं किया है - जो मुझे दृढ़ता से संदेह है)।
न घुलनेवाली तलछट
Database.ExecuteSqlCommand()
या निष्पादित कर सकते हैं DbSet<T>.SqlQuery()
।
(NOLOCK)
- बुरी आदत को किक करने के लिए देखें - हर जगह NOLOCK डालते हुए - यह हर जगह इस का उपयोग करने के लिए अनुशंसित नहीं है - काफी विपरीत!