मुझे यह पता चला:
https://entityframework.codeplex.com/wikipage?title=Interception
और ऐसा प्रतीत होता है कि आप ऐसा कुछ कर सकते हैं:
public class HintInterceptor : DbCommandInterceptor
{
public override void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
{
command.CommandText += " option (recompile)";
base.ReaderExecuting(command, interceptionContext);
}
}
और इसे इस तरह रजिस्टर करें (मैंने इसे Application_Start
. में किया था global.asax.cs
. का ):
DbInterception.Add(new HintInterceptor());
और यह आपको CommandText
. को बदलने देगा . एकमात्र समस्या यह है कि अब यह प्रत्येक . के लिए संलग्न है पाठक प्रश्न जो एक समस्या हो सकती है क्योंकि उनमें से कुछ उस संकेत से नकारात्मक रूप से प्रभावित हो सकते हैं। मुझे लगता है कि मैं संदर्भ के साथ कुछ कर सकता हूं यह पता लगाने के लिए कि संकेत उचित है या नहीं, या इससे भी बदतर स्थिति मैं CommandText
की जांच कर सकता हूं स्वयं।
सबसे सुंदर या बढ़िया समाधान नहीं लगता।
संपादित करें :interceptorContext
. से , आप DbContexts
. प्राप्त कर सकते हैं , इसलिए मैंने एक इंटरफ़ेस परिभाषित किया जो इस तरह दिखता है:
public interface IQueryHintContext
{
string QueryHint { get; set; }
bool ApplyHint { get; set; }
}
और फिर एक वर्ग बनाया जो मेरे मूल डीबीकॉन्टेक्स्ट (ईएफ द्वारा जेनरेट किया गया) से निकला है और उपर्युक्त इंटरफ़ेस लागू करता है। फिर मैंने इस तरह दिखने के लिए अपना इंटरसेप्टर बदल दिया:
public class HintInterceptor : DbCommandInterceptor
{
public override void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
{
if (interceptionContext.DbContexts.Any(db => db is Dal.IQueryHintContext))
{
var ctx = interceptionContext.DbContexts.First(db => db is Dal.IQueryHintContext) as Dal.IQueryHintContext;
if (ctx.ApplyHint)
{
command.CommandText += string.Format(" option ({0})", ctx.QueryHint);
}
}
base.ReaderExecuting(command, interceptionContext);
}
}
अब इसका उपयोग करने के लिए, मैं मूल के बजाय अपने व्युत्पन्न वर्ग का उपयोग करके एक संदर्भ बनाता हूं, QueryHint
सेट करें जो कुछ भी मैं चाहता हूं वह (recompile
इस मामले में) और ApplyHint
set सेट करें इससे पहले कि मैं कमांड निष्पादित करूं और बाद में इसे वापस असत्य पर सेट करूं।
इसे और अधिक आत्म-निहित बनाने के लिए, मैंने एक इंटरफ़ेस को इस तरह परिभाषित किया:
public interface IQueryHintContext
{
string QueryHint { get; set; }
bool ApplyHint { get; set; }
}
और इस तरह मेरे डीबी संदर्भ को बढ़ाया (आप निश्चित रूप से, ईएफ जेनरेट क्लास को भी विस्तारित करने के लिए आंशिक कक्षा का उपयोग कर सकते हैं):
public class MyEntities_Ext : MyEntities, IQueryHintContext
{
public string QueryHint { get; set; }
public bool ApplyHint { get; set; }
}
और फिर, टर्न-ऑन, टर्न-ऑफ भाग को संभालना थोड़ा आसान बनाने के लिए, मैंने इसे परिभाषित किया:
public class HintScope : IDisposable
{
public IQueryHintContext Context { get; private set; }
public void Dispose()
{
Context.ApplyHint = false;
}
public HintScope(IQueryHintContext context, string hint)
{
Context = context;
Context.ApplyHint = true;
Context.QueryHint = hint;
}
}
अब इसका उपयोग करने के लिए, मैं बस यह कर सकता हूँ:
using (var ctx = new MyEntities_Ext())
{
// any code that didn't need the query hint
// ....
// Now we want the query hint
using (var qh = new HintScope(ctx, "recompile"))
{
// query that needs the recompile hint
}
// back to non-hint code
}
यह शायद थोड़ा अधिक हो सकता है और इसे और विकसित किया जा सकता है (उदाहरण के लिए, एक स्ट्रिंग के बजाय उपलब्ध संकेतों के लिए एक एनम का उपयोग करना - या एक recompile
को उप-वर्गीकृत करना क्वेरी संकेत ताकि आपको स्ट्रिंग निर्दिष्ट करने की आवश्यकता न हो recompile
हर बार और एक टाइपो का जोखिम), लेकिन इसने मेरी तत्काल समस्या को हल कर दिया।