2010-02-16 35 views
5

मेरे पास दो इकाइयों (अभिभावक और बच्चे) के बीच माता-पिता के संबंध हैं।संग्रह से किसी आइटम को निकालना (NHibernate)

मेरे जनक मानचित्रण इस प्रकार है:

<class name="Parent" table="Parents"> 
    ... 
    <bag name="Children" cascade="all"> 
     <key column="ParentID"></key> 
     <one-to-many class="Child"></one-to-many> 
    </bag> 
</class> 

मैं निम्नलिखित निष्पादित करने के लिए करना चाहते हैं:

someParent.Children.Remove(someChild); 

बाल वर्ग, प्रकार एक और माता पिता के वर्ग के लिए एक संदर्भ है। संबंध लग रहा है

तरह

relation diagram

नोट: मैं ऊपर गैर-लिंक्ड यूआरएल लिए माफी माँगता हूँ, मैं इस के कारण मार्कअप

का उपयोग कर URL स्ट्रिंग में तारांकन पिछले मिल ही नहीं सकता था रिश्ते, जब उपरोक्त कोड कहा जाता है, तो DELETE क्वेरी के बजाय, एक अद्यतन क्वेरी उत्पन्न होती है जो बाल तालिका से (Pullid) को हटा देता है।

क्या माता-पिता से हटाए जाने पर एनएचबीर्नेट को बाल रिकॉर्ड को पूरी तरह हटाने के लिए मजबूर करना संभव है। बच्चे संग्रह?

अद्यतन

@ स्पेंसर्स समाधान

बहुत आकर्षक समाधान के रूप में यह कुछ भविष्य कक्षाओं में लागू किया जा सकता है। हालांकि, रिपोजिटरी पैटर्न में सत्रों को मेरे (मेरे विशेष मामले में) संभालने के तरीके के कारण, यह असंभव है क्योंकि हमें आवेदन के आधार पर सत्र प्रकार (CallSessionContext/WebSessionContext) पास करना होगा।

@ जैमी के समाधान

सरल और लागू करने के लिए त्वरित, फिर भी मैं पहुंच जाते हैं एक और सड़क ब्लॉक। मेरी बाल इकाई निम्नानुसार दिखती है: entity object

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

@The One-Shot-Delete solution described here, संग्रह को एक ही डिलीट करने के लिए संग्रह को संदर्भित करने के विचार को रेखांकित करता है। हालांकि ऊपर के समान परिणाम, एक अद्यतन कथन जारी किया गया है।

//Instantiate new collection and add persisted items 
List<Child> children = new List<Child>(); 
children.AddRange(parent.Children); 

//Find and remove requested items from new collection 
var childrenToRemove = children 
    .Where(c => c.Type.TypeID == 1) 
    .ToList(); 

foreach (var c in childrenToRemove) { children.Remove(m); } 
parent.Children = null; 

//Set persisted collection to new list 
parent.Children = Children; 

समाधान

खुदाई का एक सा लिया, लेकिन जैमी के समाधान के लिए कुछ अतिरिक्त संशोधनों के साथ के माध्यम से आया था। भविष्य पाठकों के लिए, ऊपर मेरी कक्षा मॉडल पर आधारित:

प्रकार मानचित्रण - उलटा = सच है, कास्केड = सभी

जनक मानचित्रण - उलटा = सच है, कास्केड = सभी को नष्ट-अनाथ

तरीके के रूप में निकालें जेमी के समाधान कार्यों में वर्णित है।यह प्रति अनाथ वस्तु के एक एकल डिलीट स्टेटमेंट का उत्पादन करता है, इसलिए भविष्य में ट्यूनिंग की संभावना है, हालांकि अंतिम परिणाम सफल है।

उत्तर

1

IList<Child> उजागर करने के बजाय, एक विधि के माध्यम से संग्रह के लिए उपयोग को नियंत्रित:

RemoveChild(Child child) 
{ 
    Children.Remove(child); 
    child.Parent = null; 
    child.Type.RemoveChild(child); 
} 

Type.RemoveChild समान विचार करेंगे, लेकिन आप सावधान करने के लिए एक दूसरे को की बुला अनंत लूप में नहीं डाल होना चाहिए था निकालें चाइल्ड विधियों।

0

मुझे नहीं लगता कि यह बिल्कुल संभव है क्योंकि हाइबरनेट को यह जानने का कोई तरीका नहीं है कि रिकॉर्ड अनाथ हो गया है या नहीं। यह जांच सकता है कि क्या कोई अन्य वर्ग बाल वर्ग से संबंधित है लेकिन फिर यह माना जाएगा कि यह पूरी डीबी संरचना से अवगत है जो मामला नहीं हो सकता है।

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

  1. आईएलिस्ट और आईएलआईस्ट <> में प्रवेश करने वाली कक्षा बनाएं और इसे CascadeDeleteList या उन पंक्तियों के साथ कुछ कहें।
  2. इस वर्ग के अंदर एक निजी .Net सूची बनाएं और इस सूची में विभिन्न विधि कॉल को प्रॉक्सी करें।
  3. आईस्कैस्डडेलेटेल्ड नामक एक इंटरफ़ेस बनाएं और इसे एक विधि दें()
  4. अपने कैस्केडडिलेटलिस्ट के लिए हटाएं विधि के तहत हटाए जाने वाले ऑब्जेक्ट के प्रकार की जांच करें। यदि यह टाइप किया गया है ICascadeDeleteChild तो इसे हटाएं विधि को कॉल करें।
  5. आईस्कैस्डडेलेटेल्ड इंटरफ़ेस को लागू करने के लिए अपने बाल वर्ग को बदलें।

मुझे पता है कि यह दर्द की तरह लगता है लेकिन एक बार ऐसा करने के बाद इन इंटरफेस को बंदरगाह के लिए सरल होना चाहिए।

+0

मेरा मानना ​​है कि इससे मुझे सही रास्ते पर पहुंचाया जा सकता है, सड़क ब्लॉक हो रहा है: इसे एक भंडार पैटर्न में स्थापित करना (यानी, इस मामले में बच्चे को हटाएं विधि अपनी खुद की भंडार विधि कहलाएगी) और उपयोग करने में भी सक्षम है यह विभिन्न सत्र संदर्भों के साथ (यानी, CallSessionContext बनाम WebSessionContext) –

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