2010-02-19 10 views
9

मेरे पास "ग्राहक" नामक एक वस्तु है जिसका उपयोग अन्य तालिकाओं में विदेशी कुंजी के रूप में किया जाएगा।कैसे एक संदर्भित वस्तु को हटाया जा सकता है?

समस्या यह है कि मैं जानना चाहता हूं कि "ग्राहक" हटाया जा सकता है (यानी, इसे किसी अन्य तालिका में संदर्भित नहीं किया जा रहा है)।

क्या यह निबर्ननेट के साथ संभव है?

+0

आप कहते हैं कि 'Customer'" अन्य तालिकाओं "में संदर्भित है। बहुवचन इरादा है? हां, * ग्राहक * संदर्भित * कई * अन्य इकाई वर्गों से है? (उत्तर संभव समाधान को प्रभावित करता है।) –

+0

@Jorn, हाँ, यह कई अन्य तालिकाओं में संदर्भित किया जा रहा है। –

उत्तर

5

आप जो पूछ रहे हैं वह संदर्भित तालिका एफके कॉलम में Customer पीके मान का अस्तित्व ढूंढना है। ऐसे कई तरीके आप इस के बारे में जान सकते हैं:

  1. रूप kgiannakakis बताया गया है, नष्ट करने की कोशिश और एक अपवाद रोलबैक फेंक दिया जाता है। प्रभावी लेकिन बदसूरत और उपयोगी नहीं है। यह भी आवश्यक है कि आपने अपने डेटाबेस में एक CASCADE = "RESTRICT" सेट किया हो। यह समाधान दोष यह है कि आप पता लगाने के लिए कि आप

  2. नक्शा नहीं कर सकते संस्थाओं है कि संग्रह के रूप में उल्लेख Customer और उसके बाद प्रत्येक संग्रह के लिए अगर उनके Count > 0 फिर हटाएं अनुमति नहीं देते वस्तु को हटाने का प्रयास करने के लिए है कि नहीं है। यह अच्छा है क्योंकि मैपिंग पूर्ण होने तक स्कीमा परिवर्तनों के खिलाफ यह सुरक्षित है। यह भी एक बुरा समाधान है क्योंकि अतिरिक्त चयन करना होगा।

  3. एक ऐसी विधि है जो bool IsReferenced(Customer cust) जैसी क्वेरी करता है। अच्छा क्योंकि आपके पास एक ही क्वेरी हो सकती है जिसका आप उपयोग करते समय उपयोग करेंगे। इतना अच्छा नहीं है क्योंकि यह स्कीमा और/या डोमेन परिवर्तनों के कारण त्रुटियों के लिए अतिसंवेदनशील हो सकता है (क्वेरी के प्रकार के आधार पर: एसक्यूएल/एचक्यूएल/मानदंड)।

  4. कक्षा पर एक गणना की गई संपत्ति <property name="IsReferenced" type="long" formula="sql-query that sums the Customer id usage in the referenced tables" /> जैसे मैपिंग तत्व के साथ स्वयं है। अच्छा क्योंकि यह एक तेज़ समाधान (कम से कम आपके डीबी के रूप में तेज़ है), कोई अतिरिक्त प्रश्न नहीं है। इतना अच्छा नहीं है क्योंकि यह स्कीमा परिवर्तनों के लिए अतिसंवेदनशील है, इसलिए जब आप अपना डीबी बदलते हैं तो आपको इस क्वेरी को अपडेट करना न भूलना चाहिए।

  5. पागल समाधान: एक स्कीमा बाध्य दृश्य बनाएं जो गणना करता है। जब आप चाहें तो उस पर क्वेरी करें।अच्छा है क्योंकि इसकी स्कीमा बाध्य और क्योंकि क्वेरी त्वरित, नहीं-तो-अच्छा है क्योंकि आप अभी भी एक अतिरिक्त क्वेरी क्या करना है (या आप समाधान 4. पर इस दृश्य की परिणाम के नक्शे)

  6. कम स्कीमा परिवर्तन करने के लिए अतिसंवेदनशील, अच्छा है

2,3,4 क्योंकि आप भी अपने यूआई के इस व्यवहार को पेश कर सकती हैं (हटाने की अनुमति नहीं है)

निजी तौर पर मुझे लगता है कि वरीयता के साथ 4,3,5 के लिए जाना होगा भी अच्छे हैं

+1

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

0

कैस्केड संपत्ति को देखने के लायक हो सकता है, विशेष रूप से आपकी एचबीएम.एक्सएमएल फाइलों में सभी डिलीट-अनाथ - और यह आपके लिए इसका ख्याल रख सकता है।

See here, 16.3 - Cascading Lifecycle

1

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

public class CustomerCanBeDeleted 
{ 

    public bool IsSatisfiedBy(Customer customer) 
    { 
     // Check that related objects are null and related collections are empty 
     // Plus any business logic that determines if a Customer can be deleted 
    } 
} 

संपादित:

शायद सबसे सरल तरीका एक संग्रहीत प्रक्रिया है कि इस चेक करता है बना सकते हैं और हटाने से पहले इसे कहते हैं होगा। आप NHibernate (ISession.Connection.CreateCommand()) से IDbCommand तक पहुंच सकते हैं ताकि कॉल डेटाबेस अज्ञेयवादी हो।

this question पर प्रतिक्रियाएं भी देखें।

0

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

2

टेबल और विदेशी कुंजी के बजाय संस्थाओं और संबंधों में सोचते हुए, इन अलग-अलग स्थितियां हैं:

  • ग्राहक एक एक-से-कई संबंध जो ग्राहक का एक हिस्सा बनाता है, उदाहरण के लिए अपने फोन नंबर के लिए है। उन्हें कैस्केडिंग के माध्यम से भी हटाया जाना चाहिए।
  • ग्राहक के पास एक-से-कई या कई से अधिक संबंध हैं जो ग्राहक का हिस्सा नहीं हैं, लेकिन वे ग्राहक द्वारा ज्ञात/पहुंच योग्य हैं।
  • कुछ अन्य इकाई के पास ग्राहक से संबंध है। यह किसी भी प्रकार का हो सकता है (जो डेटाबेस में एक विदेशी कुंजी नहीं है)। उदाहरण के लिए ग्राहक के आदेश। आदेश ग्राहक द्वारा ज्ञात नहीं हैं। यह सबसे कठिन मामला है।

जहां तक ​​मुझे पता है, NHHernate से कोई प्रत्यक्ष समाधान नहीं है। मेटा-डेटा एपीआई है, जो आपको रनटाइम पर मैपिंग परिभाषाओं का पता लगाने की अनुमति देती है। आईएमएचओ, यह करने का गलत तरीका है।

मेरी राय में, यह व्यवसाय तर्क की ज़िम्मेदारी है कि यह सत्यापित करने के लिए कि कोई इकाई हटाया जा सकता है या नहीं। (भले ही विदेशी कुंजी और बाधाएं हैं जो डेटाबेस की अखंडता सुनिश्चित करती हैं, फिर भी यह व्यवसाय तर्क है)।

हमने एक ऐसी सेवा लागू की जिसे किसी इकाई को हटाने से पहले कहा जाता है। सॉफ्टवेयर के अन्य हिस्सों कुछ प्रकार के लिए रजिस्टर करते हैं। वे हटाने के खिलाफ veto कर सकते हैं (उदाहरण के लिए एक अपवाद फेंक कर)।

उदाहरण के लिए, आदेश प्रणाली ग्राहकों के हटाने के लिए पंजीकृत करता है। यदि किसी ग्राहक को हटाया जाना चाहिए, तो ऑर्डर सिस्टम इस ग्राहक द्वारा ऑर्डर की खोज करता है और अगर उसे कोई फेंकता है तो फेंकता है।

+0

आपने मुझे व्यवसाय तर्क –

4

मुझे पता है कि अगर एक "ग्राहक" हटाए जा सकते हैं चाहते हैं (यानी, यह किसी भी अन्य तालिकाओं में संदर्भित किया जा रहा नहीं है)।

यह निर्धारित करने के लिए डेटाबेस की ज़िम्मेदारी वास्तव में नहीं है कि ग्राहक को हटाया जा सकता है या नहीं। यह आपके व्यापार तर्क का हिस्सा है।

आप डेटाबेस पर रेफरेंशियल इंटिग्रिटी जाँच करने के लिए पूछ रहे हैं।

यह गैर ओओपी दुनिया में ठीक है। लेकिन ऑब्जेक्ट्स से निपटने पर (जैसे आप करते हैं) आप अपनी ऑब्जेक्ट्स में तर्क जोड़ते हैं (ऑब्जेक्ट्स में राज्य और व्यवहार होता है; डीबी - केवल राज्य)।

तो, मैं यह निर्धारित करने के लिए ग्राहक वर्ग में एक विधि जोड़ूंगा कि इसे हटाया जा सकता है या नहीं। इस तरह आप सही ढंग से (इकाई) कार्यक्षमता परीक्षण कर सकते हैं।

उदाहरण के लिए, मान लीजिए कि हमारे पास नियम है ग्राहक को केवल तभी हटाया जा सकता है जब उसके पास कोई आदेश न हो और फोरम में भाग नहीं लिया हो।

तो फिर तुम ग्राहक वस्तु इस के समान (सरल संभव मामले) करना होगा:

public class Customer 
{ 
    public virtual ISet<Order> Orders { get; protected set; } 
    public virtual ISet<ForumPost> ForumPosts { get; protected set; } 

    public virtual bool CanBedeleted 
    { 
     get 
     { 
      return Orders.Count == 0 && ForumPosts.Count == 0 
     } 
    } 
} 

यह बहुत साफ है और सरल डिजाइन का उपयोग करने के लिए आसान है कि, परीक्षण है और भारी NHibernate या अंतर्निहित डेटाबेस पर निर्भर करता नहीं है । कि करने के लिए

if (myCustomer.CanBeDeleted) 
    session.Delete(mycustomer) 

इसके अलावा आप बेहतर बना सकते हैं NHibernate संबंधित आदेश और अन्य संगठन को हटाने के लिए यदि आवश्यक हो तो:

आप इस तरह इसका इस्तेमाल कर सकते हैं।


ध्यान दें: निश्चित रूप से उपरोक्त उदाहरण सिर्फ सरल संभव निदर्शी समाधान है। आप इस तरह के एक नियम के part of the validation कि जब ऑब्जेक्ट को हटाने से लागू किया जाना चाहिए बनाने के लिए चाहते हो सकता है।

+1

में इस बारे में सोचने के बारे में सोचा है कि आप [संग्रह] को कॉल करके कम से कम 2 अतिरिक्त चयन कर रहे हैं। गणना संपत्ति। इसके अतिरिक्त एक बुरी तरह से गठित इकाई परीक्षण (या जो अस्तित्व में नहीं है) एक शर्त पारित करेगा। यह डेटाबेस बाधाओं को लागू करके बचाया जा सकता है! यह हमेशा एक अच्छा अभ्यास है कि बैकएंड व्यापार तर्क डेटा अखंडता – Jaguar

+0

के लिए अग्रभाग पर निर्भर नहीं है आप उत्सुक fetch या अन्य तरीकों का उपयोग करके मैकिंग में एसक्यूएल को ट्यून कर सकते हैं, उद्देश्य विचार को प्रदर्शित करना था। 'यह डेटाबेस बाधाओं को लागू करके सहेजा जा सकता है' - मैंने उल्लेख किया कि यह भी सत्यापन का हिस्सा होना चाहिए। –

+0

मैं तर्क दूंगा कि डाटाबेस रेफरेंसियल अखंडता की जांच ** ** ** तर्क तर्क का हिस्सा नहीं है - मुझे लगता है कि यह केवल तभी मामला है जब आपका प्रोग्राम डेटाबेस प्रोग्राम है। – fostandy

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