c# - DbContext के लिए CommandTimeout कैसे सेट करें?




entity-framework-4 command-timeout (6)

मैं DbContext के लिए CommandTimeout सेट करने का तरीका ढूंढ रहा हूं। खोज करने के बाद मैंने DCContext को ObjectContext में डालकर और ObjectContext के CommandTimeout प्रॉपर्टी के लिए वैल्यू सेट करने का तरीका खोज लिया।

var objectContext = (this.DbContext as IObjectContextAdapter).ObjectContext;

लेकिन मुझे DbContext के साथ काम करना है।


मुझे एक्सटेंशन दृष्टिकोण पसंद है:

public static class DbContextExtensions
{
   public static void SetCommandTimeout(this ObjectContext dbContext,
       int TimeOut)
   {
       dbContext.CommandTimeout = TimeOut;
   }
}

और फिर बस

((IObjectContextAdapter)cx).ObjectContext.SetCommandTimeout(300);

मुझे लगता है कि मेरे लिए .tt फ़ाइल को बदलना मेरे लिए काम करता है क्योंकि मैं बाद में परिवर्तन को नहीं खोता:

इस पंक्ति को जोड़ें:

((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;

DbContext निर्माता के बाद और लोडर से पहले

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
    public <#=code.Escape(container)#>()
        : base("name=<#=container.Name#>")
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
<#
if (!loader.IsLazyLoadingEnabled(container))

यह तब आपके उत्पन्न हुए संदर्भों में प्रकट होना चाहिए:

public MyEntities()
            : base("name=MyEntities")
        {
            ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
        }

यदि यह मदद कर सकता है, तो यह VB.Net समाधान है:

Dim objectContext As Objects.ObjectContext = CType(Me,IObjectContextAdapter).ObjectContext
objectContext.commandTimeout = connectionTimeout

यह आपकी मदद कर सकता है।

public class MyContext : DbContext
{    
    public MyContext () : base(ContextHelper.CreateConnection("my connection string"), true)
    {
        ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 300;
    }
}

यहां बताया गया है कि ईडीएमएक्स फ़ाइल का उपयोग करते समय मैंने इस समस्या को कैसे हल किया। यह समाधान जनरेट किए गए वर्ग को कस्टम DbContext वर्ग से इनहेरिट करने के लिए डिफ़ॉल्ट T4 टेम्प्लेट को बदलता है, जो एक डिफ़ॉल्ट कमांड टाइमआउट और इसे बदलने के लिए एक प्रॉपर्टी को निर्दिष्ट करता है।

मैं विजुअल स्टूडियो 2012 और ईएफ 5.0 का उपयोग कर रहा हूं। आपका अनुभव अन्य संस्करणों के साथ भिन्न हो सकता है।

एक कस्टम DbContext क्लास बनाएँ

public class CustomDbContext : DbContext
{
    ObjectContext _objectContext;

    public CustomDbContext( string nameOrConnectionString )
        : base( nameOrConnectionString )
    {
        var adapter = (( IObjectContextAdapter) this);

        _objectContext = adapter.ObjectContext;

        if ( _objectContext == null )
        {
            throw new Exception( "ObjectContext is null." );    
        }

        _objectContext.CommandTimeout = Settings.Default.DefaultCommandTimeoutSeconds;
    }

    public int? CommandTimeout
    {
        get
        {
            return _objectContext.CommandTimeout;
        }
        set
        {
            _objectContext.CommandTimeout = value;
        }
    }
}

इसमें एक वैकल्पिक विशेषता है: मैं डिफ़ॉल्ट कमांड टाइमआउट को हार्ड-कोडिंग नहीं कर रहा हूं। इसके बजाय, मैं इसे प्रोजेक्ट सेटिंग्स से लोड कर रहा हूं ताकि मैं एक कॉन्फ़िगर फ़ाइल में मान बदल सकूं। प्रोजेक्ट सेटिंग्स को सेटअप और उपयोग कैसे करें, इस उत्तर के दायरे में नहीं है।

मैं कनेक्शन स्ट्रिंग या कनेक्शन स्ट्रिंग नाम को हार्ड-कोडिंग भी नहीं कर रहा हूं। यह पहले से ही उत्पन्न संदर्भ वर्ग द्वारा निर्माणकर्ता में पारित हो गया है, इसलिए इसे यहां हार्ड-कोड करने का कोई मतलब नहीं है। यह कोई नई बात नहीं है; ईडीएमएक्स फ़ाइल पहले से ही आपके लिए निम्नलिखित निर्माणकर्ता है, इसलिए हम अभी मूल्य के साथ गुजर रहे हैं।

public MyEntities()
    : base("name=MyEntities")
{
}

(यह विन्यास फाइल से "MyEntities" नामक कनेक्शन स्ट्रिंग को लोड करने के लिए EF को निर्देश देता है।)

मैं एक कस्टम अपवाद फेंक रहा हूँ अगर ObjectContext कभी शून्य है। मुझे नहीं लगता कि यह कभी होगा, लेकिन यह NullReferenceException प्राप्त करने से अधिक सार्थक है।

मैं ObjectContext को एक क्षेत्र में संग्रहीत करता ObjectContext ताकि मैं डिफ़ॉल्ट को ओवरराइड करने के लिए इसे एक्सेस करने के लिए एक संपत्ति बना ObjectContext

इकाई संदर्भ T4 टेम्पलेट को संशोधित करना

समाधान एक्सप्लोरर में, EDMX फ़ाइल का विस्तार करें ताकि आप T4 टेम्पलेट देखें। उनका .tt एक्सटेंशन है।

इसे खोलने के लिए "MyModel.Context.tt" फ़ाइल पर डबल क्लिक करें। 57 रेखा के आसपास आपको यह देखना चाहिए:

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext

यह टेम्पलेट लाइन आपके "MyEntities" वर्ग की वर्ग परिभाषा उत्पन्न करती है, जो DbContext को विरासत में मिलती है।

लाइन को बदलें ताकि उत्पन्न वर्ग को इसके बजाय CustomDbContext विरासत में मिले:

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : CustomDbContext

जैसे ही आप इस फ़ाइल को सहेजते हैं, इसे कक्षा को पुन: उत्पन्न करना चाहिए। यदि नहीं, तो आप ईडीएमएक्स फ़ाइल पर राइट-क्लिक कर सकते हैं और "रन कस्टम टूल" का चयन कर सकते हैं। यदि आप अपनी EDMX फ़ाइल के अंतर्गत "MyModel.Context.tt" फ़ाइल का विस्तार करते हैं, तो आपको "MyModel.Context.cs" दिखाई देगा। वह जनरेट की गई फ़ाइल है। इसे खोलें, और आपको यह देखना चाहिए कि यह अब CustomDbContext विरासत में CustomDbContext

public partial class MyEntities : CustomDbContext

यही सब है इसके लिए।

मुद्दे

एक बार जब आप संदर्भ श्रेणी को DbContext से DbContext में CustomDbContext , तो विजुअल स्टूडियो आपको एक त्रुटि देगा, यदि आप Entity Framework / टेम्पलेट का उपयोग करके "कंट्रोलर विद रीड / राइट एक्शन एंड व्यूज़" का उपयोग करके एक नया MVC कंट्रोलर क्लास जोड़ने का प्रयास करें। यह कहेगा "असमर्थित संदर्भ प्रकार।" इसके आस-पास जाने के लिए, उत्पन्न "MyModel.Context.cs" वर्ग खोलें, और अस्थायी रूप से इसे DbContext वापस आ जाता है। अपने नए नियंत्रक को जोड़ने के बाद, आप इसे वापस CustomDbContext बदल सकते हैं।


var ctx = new DbContext();
ctx.Database.CommandTimeout = 120;




command-timeout