2013-04-30 4 views
6

मैं EF5 उपयोग कर रहा हूँ और मेरे संदर्भ के लिए POCO संस्थाओं का एक कट ग्राफ संलग्न, कुछ धीमी है: -इकाई की रूपरेखा - "अटैच()" इस तरह

using (var context = new MyEntities()) 
{ 
    context.Configuration.AutoDetectChangesEnabled = false; 

    context.MyEntities.Attach(myEntity); 

    // Code to walk the entity graph and set each entity's state 
    // using ObjectStateManager omitted for clarity .. 

    context.SaveChanges(); 
} 

इकाई "myEntity" एक बड़ी है कई बच्चों के संग्रह के साथ इकाइयों का ग्राफ, जो बदले में अपने स्वयं के बच्चे के संग्रह होते हैं, और इसी तरह। पूरे ग्राफ में 10000 इकाइयों के क्रम में शामिल है, लेकिन आमतौर पर केवल एक छोटी संख्या बदल जाती है।

इकाई राज्यों को सेट करने के लिए कोड और वास्तविक SaveChanges() काफी तेज़ है (< 200ms)। यह Attach() है जो यहां समस्या है, और इसमें 2.5 सेकंड लगते हैं, इसलिए मैं सोच रहा था कि यह बेहतर हो सकता है या नहीं। मैंने लेख देखे हैं जो आपको AutoDetectChangesEnabled = false सेट करने के लिए बताते हैं, जो मैं ऊपर कर रहा हूं, लेकिन इससे मेरे परिदृश्य में कोई फर्क नहीं पड़ता। ऐसा क्यों है?

उत्तर

2

मुझे डर है कि 10000 इकाइयों के साथ ऑब्जेक्ट ग्राफ़ को जोड़ने के लिए 2,5 सेकंड "सामान्य" है। यह शायद इकाई स्नैपशॉट निर्माण है जो तब होता है जब आप इस समय लेते हुए ग्राफ संलग्न करते हैं।

हैं "केवल एक छोटी संख्या आम तौर पर बदल रहे हैं" - कहते हैं कि 100 - आप उदाहरण के लिए, डेटाबेस से मूल निकाय लोड और पूरे ग्राफ संलग्न के अपने गुणों को बदलने के बजाय करने के लिए विचार कर सकते हैं:

using (var context = new MyEntities()) 
{ 
    // try with and without this line 
    // context.Configuration.AutoDetectChangesEnabled = false; 

    foreach (var child in myEntity.Children) 
    { 
     if (child.IsModified) 
     { 
      var childInDb = context.Children.Find(child.Id); 
      context.Entry(childInDb).CurrentValues.SetValues(child); 
     } 
     //... etc. 
    } 
    //... etc. 

    context.SaveChanges(); 
} 

यद्यपि यह बहुत सारे डेटाबेस प्रश्नों को बनाएगा, फिर भी नेविगेशन गुणों के बिना केवल "फ्लैट" इकाइयों को लोड किया जाएगा और संलग्न किया जाएगा (जो Find पर कॉल करते समय होता है) अधिक समय नहीं लेगा। प्रश्नों की संख्या को कम करने के लिए आप भी एक Contains क्वेरी का उपयोग कर एक "बैच" के रूप में एक ही प्रकार के संस्थाओं लोड करने का प्रयास कर सकते हैं:

var modifiedChildIds = myEntity.Children 
     .Where(c => c.IsModified).Select(c => c.Id); 

    // one DB query 
    context.Children.Where(c => modifiedChildIds.Contains(c.Id)).Load(); 

    foreach (var child in myEntity.Children) 
    { 
     if (child.IsModified) 
     { 
      // no DB query because the children are already loaded 
      var childInDb = context.Children.Find(child.Id); 
      context.Entry(childInDb).CurrentValues.SetValues(child); 
     } 
    } 

यह इस धारणा के तहत सिर्फ एक सरल उदाहरण केवल अदिश गुण बदलने के लिए है कि आप है संस्थाओं का। रिश्ते में संशोधन (बच्चों को संग्रह से जोड़ा गया है और/या हटाया गया है, आदि) में मनमाने ढंग से अधिक जटिल हो सकता है।

+0

बहुत धन्यवाद, यह जानना उपयोगी है। –

संबंधित मुद्दे