NHibernate में चाइल्ड ऑब्जेक्ट कैसे हटाएं?


79

मेरे पास एक अभिभावक वस्तु है जिसका बाल वस्तुओं के IList के साथ कई संबंध हैं। बाल वस्तुओं को हटाने का सबसे अच्छा तरीका क्या है? मैं माता-पिता को नहीं हटा रहा हूं। मेरी मूल वस्तु में बाल वस्तुओं का IList है। यहाँ एक से कई संबंधों के लिए मानचित्रण है:

<bag name="Tiers" cascade="all">
  <key column="mismatch_id_no" />
  <one-to-many class="TGR_BL.PromoTier,TGR_BL"/>
</bag>

अगर मैं स्पष्ट () का उपयोग करके संग्रह से सभी वस्तुओं को हटाने का प्रयास करता हूं, तो SaveOrUpdate () को कॉल करें, मुझे यह अपवाद मिलता है:

System.Data.SqlClient.SqlException: Cannot insert the value NULL into column

यदि मैं व्यक्तिगत रूप से बाल वस्तुओं को हटाने की कोशिश करता हूं, तो उन्हें माता-पिता से हटा दें, मुझे एक अपवाद मिलता है:

deleted object would be re-saved by cascade

NHibernate में बाल वस्तुओं को हटाने से निपटने का यह मेरा पहला अवसर है। मैं क्या गलत कर रहा हूं?

संपादित करें: बस स्पष्ट करने के लिए - मैं मूल वस्तु को हटाने की कोशिश नहीं कर रहा हूं, बस बच्चे वस्तुओं। मेरे पास माता-पिता के लिए एक के रूप में कई रिश्ते हैं। क्या मुझे चाइल्ड ऑब्जेक्ट मैपिंग पर कई-से-एक संबंध बनाने की भी आवश्यकता है?

जवाबों:


139

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

आपको दूसरी त्रुटि मिल रही है क्योंकि जब आप SaveOrUpdate NHibernate को कॉल करते हैं तो सबसे पहले बच्चे की सभी वस्तुओं को हटा देता है। फिर, क्योंकि न तो रिश्ते को उलटा के रूप में चिह्नित किया जाता है, NHibernate भी आपके बच्चे की तालिका में विदेशी कुंजी कॉलम को शून्य करने की कोशिश करता है। चूंकि पंक्तियों को पहले ही हटा दिया गया है, इसलिए आपको दूसरी त्रुटि मिलती है। इसे ठीक करने के लिए आपको अपने रिश्ते के एक तरफ उलटा = सही सेट करना होगा। यह आमतौर पर एक (प्राथमिक कुंजी या मूल) पक्ष पर किया जाता है। यदि आप ऐसा नहीं करते हैं, तो NHibernate संबंध के प्रत्येक पक्ष के लिए उपयुक्त अपडेट करेगा। दुर्भाग्य से, दो अपडेट चलाना उचित काम नहीं है।

आपको हमेशा अपने रिश्तों के एक पक्ष को व्युत्क्रम के रूप में चिह्नित करना चाहिए। आप कैसे कोड के आधार पर, आपको कैस्केडिंग का उपयोग करने की आवश्यकता हो सकती है या नहीं। यदि आप एक शॉट डिलीट का लाभ उठाना चाहते हैं, जैसा कि आप Clear () का उपयोग करने की कोशिश कर रहे हैं, तो आपको अपने कैस्केड को परिभाषित करने की आवश्यकता है।


बस स्पष्ट करने के लिए - मुझे केवल मूल वस्तु पर परिभाषित संबंध मिल गया है। मैंने उस ऑब्जेक्ट पर कैस्केड को "सभी" और "ऑल-डिलीट-ऑर्फन" दोनों समय एक ही परिणाम के साथ सेट करने का प्रयास किया है। आपका मतलब है कि मुझे बच्चे की वस्तु पर एक-से-एक संबंधों को परिभाषित करने की आवश्यकता है?
मार्क स्ट्रूजिन्स्की

और इस मामले में उलटा = "सच" माता-पिता या बच्चे की वस्तु पर निर्भर करता है?
मार्क स्ट्रूजिन्स्की

3
यह उस वर्ग से संबंधित है जो विदेशी कुंजी नहीं रखता है ... आमतौर पर अभिभावक।
pmlarocque

इस स्पष्टीकरण के लिए धन्यवाद, फिर से एक उलटा मुद्दा मुझे पकड़ लिया, और यह देखकर समझाया कि यह वास्तव में मदद करता है।
मार्क डिकिंसन

यह वास्तव में मेरे पास एक समस्या को हल करने में मदद करता है। धन्यवाद।
रॉबिन रॉबिन्सन

3

चक के उत्तर के अनुसार, मैंने पेरेंट साइड मैपिंग में उलटा = सच जोड़कर अपनी समस्या हल कर ली है:

संदेश में कई संदेश हैं:

[HasMany(typeof(MessageSentTo), Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = true)]
public IList<MessageSentTo> MessageSendTos
{
    get { return m_MessageSendTo; }
    set { m_MessageSendTo = value; }
}

मैं कैसल ActiveRecord का उपयोग कर रहा हूं। धन्यवाद चक


2

SaveOrUpdate () के बजाय मर्ज () का उपयोग करने का प्रयास करें। यह भी सुनिश्चित करें कि आपका कैस्केड ऑल-डिलीट-ऑर्फ़न पर सेट है और आपका पेरेंट-चाइल्ड रिलेशनशिप इनवर्टेड है (पेरेंट पर सही = उल्टा है और फिर बच्चे में एक फील्ड जो नॉट-नॉल के साथ पैरेंट-आईडी है - यह सच है) ।


2

हमारे उदाहरण में हमारे पास कई उत्पादों के साथ श्रेणियां हैं जहां एक उत्पाद अशक्त नहीं है।

आप उत्पाद को हटाने और फ्लश से पहले माता-पिता के संग्रह से इसे हटाकर समस्या के आसपास काम कर सकते हैं लेकिन हम अभी भी इसके बेहतर समाधान की तलाश कर रहे हैं।

product = pRepo.GetByID(newProduct.ProductID);
product.Category.Products.Remove(product);
pRepo.Delete(product);

आशा है कि यह वैसे भी मदद करता है


1
हालांकि इसके लिए एक और भंडार की आवश्यकता होती है।
UpTheCreek

0

कैस्केड विशेषता मान को "सभी" से "सभी-हटाएं-अनाथ" में बदलें।


इसकी कोशिश की। मुझे अब भी वही अपवाद मिल रहा है।
मार्क स्ट्रुज़िंस्की

16
जब आप पेरेंट को हटाते हैं तो ऑल-डिलीट-अनाथ बच्चों को हटा देता है। यह इस तरह के बारे में पूछ रहा है जैसे बच्चों को हटाने के साथ कुछ नहीं करना है।
काइल वेस्ट

-3

सेट न-नल = इस मुद्दे के कारण स्तंभ पर अपनी मैपिंग में सच। मुझे सटीक सिंटैक्स पर यकीन नहीं है, हालांकि (क्षमा करें)।


ठीक है, मैं कॉलम को नॉट-नल = "सही" पर सेट करता हूं, जो चाइल्ड ऑब्जेक्ट की मैपिंग पर है। इसलिए, मैं बच्चे की वस्तुओं के IList पर स्पष्ट () विधि को कॉल करता हूं, फिर एक SaveOrUpdate () का प्रयास करें। मुझे अभी भी "स्तंभ में मान को पूर्ण रूप से सम्मिलित नहीं किया जा रहा है" त्रुटि हो रही है। क्या मैं कुछ और गलत कर रहा हूँ?
मार्क स्ट्रूजिंस्की

त्रुटि किस स्तंभ पर डाली जा रही है? आप वास्तव में अपने मॉडल में बच्चों को कैसे हटा रहे हैं?
काइल वेस्ट

मैं अपने मूल ऑब्जेक्ट में Ilist चाइल्ड ऑब्जेक्ट पर स्पष्ट () पद्धति को कॉल कर रहा हूं। तब मैं पेरेंट पर SaveOrUpdate () कह रहा हूं।
मार्क स्ट्रूजिन्स्की
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.