2010-12-13 9 views
6

संयुक्त नई और संशोधित अलग पीओसीओ इकाइयों को बचाने के लिए उचित और तेज़ तरीका क्या है?इकाई फ्रेमवर्क में संयुक्त (नई + संशोधित) अलग-अलग इकाइयों को कैसे सहेजना है?

मैं इन तरीकों के बारे में सोच रहा था:

private void Method_2(IList<Entity> entities) //detached entities 
    { 
     //This method is using SELECT to check if entity exist 
     using (var context = new ModelContainer()) 
     { 
      foreach (Entity entity in entities) 
      { 
       var foundEntity = context.CreateObjectSet<Entity>().SingleOrDefault(t => t.Id == entity.Id); 
       context.Detach(foundEntity); //Remove it from ObjectStateManager 

       if (foundEntity != null)//It is modified entity 
       { 
        context.AttachTo("EntitySet", entity); //Attach our entity 
        context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified); //We know it exists 
       } 
       else//It is new entity 
       { 
        context.CreateObjectSet<Entity>().AddObject(entity); 
       } 
      } 
      context.SaveChanges(); 
     } 
    } 

    private void Method_1(IList<Entity> entities) //detached entities 
    { 
     //This method doesn't select anything from DB, but i have ta call Savechanges after each object 
     using (var context = new ModelContainer()) 
     { 
      foreach (Entity entity in entities) 
      { 
       try 
       { 
        context.AttachTo("EntitySet", entity); 
        context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified); 
        context.SaveChanges(); 
       } 
       catch (OptimisticConcurrencyException) 
       { 
        context.ObjectStateManager.ChangeObjectState(entity, EntityState.Added); 
        context.SaveChanges(); 
       } 
      } 
     } 
    } 

जब आप अलग वातावरण में काम कर रहे हैं आप को पता है जो इकाई जोड़ दिया गया है और जो संशोधित किया गया है - यह इस जानकारी रखने के लिए और प्रदान करने के लिए आपकी जिम्मेदारी है ऑब्जेक्ट कॉन्टेक्स्ट पर।

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

+0

डब्ल्यूसीएफ के माध्यम से डीबी को सिंक करने के लिए इकाई फ्रेमवर्क का उपयोग करना एक बुरा विचार था, यह बहुत धीमा काम करता है, मैं कस्टम लाइटवेट शुद्ध एडीओ .NET डेटा एक्सेस लेयर के साथ डीटीओ का उपयोग कर समाप्त हुआ। –

उत्तर

4

जब आप अलग वातावरण में काम कर रहे हों तो आपको पता होना चाहिए कि कौन सी इकाई जोड़ा गया था और जिसे संशोधित किया गया है - यह जानकारी आपकी ऑब्जेक्ट को रखने और ऑब्जेक्ट कॉन्टेक्स्ट को प्रदान करने की आपकी ज़िम्मेदारी है।

बहुत आसान तरीका है:

foreach (var entity in entities) 
{ 
    if (entity.Id == 0) // 0 = default value: means new entity 
    { 
    // Add object 
    } 
    else 
    { 
    // Attach object and set state to modified 
    } 
} 

उदाहरण की आवश्यकता है कि आप कुछ db स्वत: जनरेट प्राथमिक कुंजी (आईडी) है।

कुछ तरीकों के साथ आपकी विधि 2 संभव है। जब आप इसे लोड करते हैं तो इकाई को अलग करने की आवश्यकता नहीं होती है। इसके बजाय ApplyCurrentValues का उपयोग करें। जब आप एकल इकाई के बजाय ऑब्जेक्ट ग्राफ़ के साथ काम करने का निर्णय लेते हैं तो पहले लोडिंग इकाई के साथ दृष्टिकोण बहुत उपयोगी होता है। लेकिन ऑब्जेक्ट ग्राफ़ के मामले में आपको मैन्युअल रूप से सिंक्रनाइज़ेशन करना होगा। ApplyCurrentValues ​​केवल स्केलर (गैर नेविगेशन) गुणों के लिए काम करता है। आप इकाइयों को एक-एक करके लोड करने के बजाय डेटाबेस में सिंगल राउंडट्रिप में आवश्यक एंटीसाइट्स लोड करने के लिए अपनी विधि को अनुकूलित करने का प्रयास कर सकते हैं।

आपका तरीका 1 भयानक समाधान है। प्रोग्राम प्रवाह को नियंत्रित करने के लिए डेटाबेस सर्वर पर उठाए गए अपवादों का उपयोग करना खराब दृष्टिकोण है।

+0

मैं डेटाबेस को सिंक्रनाइज़ करने के लिए इकाइयों को डब्ल्यूसीएफ प्राप्त कर रहा हूं, इसलिए पीके के लिए डिफ़ॉल्ट मान का मतलब कुछ भी नहीं है। –

0

शायद स्वयं ट्रैकिंग पॉको इकाइयों पर एक नज़र डालें। आईएमएचओ वे किसी भी परिदृश्य के लिए एकदम सही हैं जिसके लिए इकाई को संदर्भ से अलग किया जाना आवश्यक है। यह आपके लिए सभी नलसाजी कोड का ख्याल रखता है।

+0

मेरी डब्ल्यूसीएफ सेवा न केवल .NET क्लाइंट्स द्वारा उपयोग की जाती है, हमारे पास PHP क्लाइंट भी हैं, और वैसे भी मुझे नहीं लगता कि इकाई स्थिति पर ग्राहक जानकारी पर भरोसा करना एक अच्छा विचार है, PHP कुछ भी ट्रैक नहीं करता है ... –

1

मैं @ लैडिस्लाव से सहमत हूं - विधि_1 एक खराब दृष्टिकोण है। डेटाबेस को अपवादों को उठाएं जो ईएफ द्वारा पकड़े जाते हैं - इन अपवादों को स्वयं न करें और निगलें। के रूप में मैं भी एक अलग संदर्भ है (POCO का, कोई परिवर्तन नहीं ट्रैकिंग, ASP.NET MVC) -

विधि 1. साथ सही रास्ते पर आपका

यहाँ है कैसे मैं यह कर।

BLL इंटरफ़ेस: (ध्यान दें मैं अपने मॉडल में टीपीटी है, इसलिए जेनरिक "पोस्ट" सार है।)

void Add(Post post); 
void Update<TPost>(TPost post) where TPost : Post, new(); 

new() बाधा महत्वपूर्ण है - तुम क्यों शीघ्र ही देखेंगे।

मैं नहीं दिखाया जाएगा मैं कैसे "जोड़ें" है, क्योंकि यह के रूप में आपको लगता है आसान है - AddObject(entity);

"अपडेट" मुश्किल हिस्सा है:

public class GenericRepository<T> : IRepository<T> where T : class 
{ 
    public void Update<T2>(T2 entity) where T2: class, new() 
    { 
     var stub = new T2(); // create stub, now you see why we need new() constraint 

     object entityKey = null; 
     // ..snip code to get entity key via attribute on all domain entities 
     // once we have key, set on stub. 

     // check if entity is already attached.. 
     ObjectStateEntry entry; 
     bool attach; 

     if (CurrentContext.ObjectStateManager.TryGetObjectStateEntry(CurrentContext.CreateEntityKey(CurrentContext.GetEntityName<T>(), stub), out entry)) 
     { 
     // Re-attach if necessary. 
     attach = entry.State == EntityState.Detached; 
     } 
     else 
     { 
     // Attach for first time. 
     attach = true; 
     } 

     if (attach) 
     CurrentEntitySet.Attach(stub as T); 

     // Update Model. (override stub values attached to graph) 
     CurrentContext.ApplyCurrentValues(CurrentContext.GetEntityName<T>(), entity); 
    } 
} 

और वह मेरे लिए काम करता है।

इकाई कुंजी के लिए, मैंने अपने डोमेन वर्गों पर विशेषताओं का उपयोग किया है। एक विकल्प (जिसे मैं आगे बढ़ने वाला हूं) में, मेरे सभी डोमेन इकाइयां एक इंटरफ़ेस को लागू करती हैं, जो निर्दिष्ट करती है कि सभी डोमेन इकाइयों में "EntityKey" नामक एक संपत्ति होनी चाहिए। तब मैं अपनी बाधाओं पर उस इंटरफ़ेस का उपयोग करूंगा। असल में, मुझे एक सामान्य भंडार में स्टब इकाइयों को बनाने के लिए एक गतिशील तरीका की आवश्यकता थी।

मुझे व्यक्तिगत रूप से "आईडी की जांच करने का विचार पसंद नहीं है, अगर इसका 0 है तो यह अपडेट है"। क्योंकि मैं एएसपी.नेट एमवीसी के साथ काम कर रहा हूं, अगर मैं (या कोई अन्य डेवलपर) दृश्य को आईडी को बांधना भूल जाता है, तो यह पारित नहीं होगा, भले ही यह एक अद्यतन हो, क्योंकि आईडी == 0 इसे जोड़ा जाएगा।

मुझे ऑपरेशन के बारे में स्पष्ट होना पसंद है। इस तरह, मैं पृथक सत्यापन तर्क जोड़ें/अपडेट कर सकता हूं।

+0

यह नहीं है इतना भयानक अपवाद, इसका मतलब केवल 0 पंक्तियों को अपडेट किया गया था जबकि 1 की उम्मीद थी। –

+0

लेकिन कैच ब्लॉक में आपका निष्पादन कोड - एक बुरा विचार। कैच ब्लॉक को लॉगिंग, री-फेंक इत्यादि करना चाहिए - फिर से SaveChanges को कॉल न करें। – RPM1984

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