2011-12-02 21 views
16

तो यहां परिदृश्य है:ईएफ कोड पहले: डीडीडी का पालन करते समय किसी इकाई के संग्रह से पंक्ति को कैसे हटाएं?

डीडीडी का कहना है कि आप कुल रूट प्राप्त करने के लिए एक भंडार का उपयोग करते हैं, फिर इसका उपयोग किसी भी संग्रह में जोड़ने/निकालने के लिए करें।

जोड़ना आसान है, Collection पर आप .Add(Item item) पर सरल कॉल को जोड़ना चाहते हैं। जब आप सहेजते हैं तो डेटाबेस में एक नई पंक्ति जोड़ दी जाती है। हालांकि, हटाना अलग है - .Remove(Item item) कॉलिंग डेटाबेस से आइटम को नहीं हटाता है, यह केवल विदेशी कुंजी को हटा देता है। तो, हां, यह तकनीकी रूप से अब संग्रह का हिस्सा नहीं है, यह अभी भी डेटाबेस में है।

आसपास पढ़ना, डेटा संदर्भ का उपयोग करके इसे हटाना एकमात्र समाधान है। लेकिन डीडीडी के मुताबिक डोमेन ऑब्जेक्ट को डेटा संदर्भ से अवगत नहीं होना चाहिए, इसलिए हटा देना होगा डोमेन के बाहर करना होगा।

इस बारे में जाने का सही तरीका क्या है? या अनाथों से भरा डेटाबेस छोड़ रहा है (शायद उन्हें बाहर निकालने के लिए एक दिनचर्या चल रहा है)?

उत्तर

10

मैंने इस समस्या को उस एप्लिकेशन में हल किया है जिसका मैं वर्तमान में domain events का उपयोग करके काम कर रहा हूं; एक डीडीडी अवधारणा Eric Evans said अपनी पुस्तक में होना चाहिए था।

जबकि डोमेन वस्तुओं वस्तु संदर्भ के बारे में पता करने के लिए अनुमति नहीं है, एक IDomainEventHandler है - इसलिए मैं एक DomainObjectDeletionHandler जो हटाता वस्तु संदर्भ से पहले अपने आवेदन परत को नियंत्रण रिटर्न और परिवर्तन कर रहे हैं से 'हटाया' वस्तुओं मिल गया है बचाया।

अधिक जानकारी के लिए, मैंने डोमेन कार्यक्रमों के कार्यान्वयन के बारे में a blog लिखा है और मैंने सब कुछ एक साथ जोड़ने के लिए कैसे संपर्क किया है।

आशा में मदद करता है :)

संपादित

उदाहरण के लिए, यदि आप एक Order वर्ग किस प्रकार OrderItem के OrderItems संग्रह है है:

public class Order 
{ 
    // Other stuff 

    public void RemoveOrderItem(int orderItemId) 
    { 
     var orderItemToRemove = OrderItems.First(oi => oi.Id == orderItemId) 

     OrderItems.Remove(orderItemToRemove); 

     DomainEvents.Raise(new OrderItemRemoved(orderItemToRemove)); 
    } 
} 
+0

शानदार, – highace

+0

पर स्पॉट, जब आप विलोपन ईवेंट को ठीक से उठाएंगे? –

+0

हटाए गए डोमेन ऑब्जेक्ट पर किसी विधि से - मैंने उत्तर अपडेट किया है। –

2

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

लेकिन चूंकि मुझे नहीं पता कि मैं उस पर भरोसा कर सकता हूं, इसलिए मैंने स्वयं जिस समाधान का उपयोग किया है, वह ईएफ को इसे जिस तरह से संभालता है, उसे 'अलग' (ईएफ शर्तों में नहीं) को ठीक करने के लिए है SaveChanges() को कॉल करें, सभी संशोधित इकाइयों पर गिनती करें और राज्य को उचित रूप से हटाए जाने के लिए बदल दें।

+1

ईएफ के संदर्भ में इसे [पहचान संबंध] कहा जाता है (http://stackoverflow.com/questions/4922228/entity-framework-4-delete-object-from-entity-collection/4925040#4925040)। –

4

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

यदि आप डीबीकॉन्टेक्स्ट का उपयोग करके इसे स्पष्ट रूप से निकालना नहीं चाहते हैं, तो आप इसका उपयोग "रिलेशनशिप पहचानना" (http://msdn.microsoft.com/en-us/library/ee373856.aspx नीचे) पर कर सकते हैं।

चाल माता-पिता की प्राथमिक कुंजी सहित बच्चे पर एक समग्र प्राथमिक कुंजी सेट करना है।

एक बार ऐसा करने के बाद, माता-पिता के संग्रह से इकाई को हटाते समय, इसे तालिका से भी हटा दिया जाएगा।

+0

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

0

दो रिपॉजिटरीज़ का उपयोग क्यों नहीं करें?

var parent = ParentRepo.Get(parentId); 
parent.Children.Remove(childId); // remove it from the property Collection 
ChildRepo.Delete(childId); // delete it from the database 
ParentRepo.Commit(); // calls underlying context.SaveChanges() 

मान लिया जाये कि आप, आईओसी/डि के माध्यम से संदर्भों साझा कर रहे हैं एक रेपो के साथ प्रतिबद्ध दोनों के लिए प्रतिबद्ध होगा बुला, अन्यथा सिर्फ ChildRepo.Commit रूप में अच्छी तरह कहते हैं।