2010-02-05 6 views
8

मैं 1: 0,1 रिश्तों को मॉडल करने का सबसे अच्छा तरीका खोजने के लिए संघर्ष कर रहा हूं ("एक हो सकता है" या "सबसे अधिक है")। मुझे विश्वास है कि इसे जेड कार्डिनालिटी कहा जाता है।एक से शून्य या एक रिश्तों को मॉडलिंग (जेड कार्डिनालिटी)

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

मैं चाहते हैं होने के लिए मेरी सार्वजनिक इंटरफ़ेस:

Widget 
    WidgetTest { get; set; } 

WidgetTest 
    Widget { get; } 

मॉडल 1: विजेट एक WidgetTest संपत्ति है और डेटाबेस में विजेट तालिका WidgetTest करने के लिए एक विशिष्ट विवश विदेशी कुंजी है। मेरा डीबीए तर्क देता है कि यह विजेट के बिना विजेटटेस्ट रिकॉर्ड मौजूद होने की अनुमति देगा।

WidgetTable 
    WidgetTestId (FK, UQ) 

मॉडल 2: विजेट WidgetTest की एक निजी संग्रह है और जोड़ने या संग्रह के लिए एक सार्वजनिक WidgetTest संपत्ति के द्वारा नियंत्रित से एक वस्तु को हटाने के द्वारा 0,1 संबंध लागू करता है। डेटाबेस मॉडल 1: एम के साथ विजेटटेस्ट के साथ विजेट के लिए एक विशिष्ट रूप से बाधित विदेशी कुंजी है। मैं तर्क देता हूं कि इसका मतलब डेटाबेस स्कीमा फिट करने के लिए मॉडल को अपनाना है (यानी मेरे लिए और अधिक काम)।

WidgetTestTable 
    WidgetId (FK, UQ) 

कौन सा मॉडल बेहतर है? NHibernate के साथ हासिल करना आसान है? या क्या कोई तीसरा तरीका है?

संपादित करें ... यहाँ है कि मैं क्या साथ समाप्त हो गया है:

public class Widget 
{ 
    // This is mapped in NH using a access strategy 
    private IList<WidgetTest> _widgetTests = new List<WidgetTest>(1); 

    public WidgetTest 
    { 
     get { return _widgetTests.FirstOrDefault(); } 
     set 
     { 
      _widgetTests.Clear(); 
      if (value != null) 
      { 
       _widgetTests.Add(value); 
      } 
     } 
    } 
} 
+0

क्या एक 1 के साथ गलत :? पीके-पीके द्वारा लागू मैपिंग जो काफी सीधे आगे .. –

उत्तर

4

मैपिंग में एक से कई रिश्तों को मॉडल करने के लिए मेरा दृष्टिकोण है, लेकिन एक ही आइटम में "कई" को बाधित करने के लिए। यह वैकल्पिक एक-से-एक की अनुमति देता है, और यह भी गारंटी देता है कि जब आप विजेट को सहेजते हैं तो आपका विजेटटेस्ट उदाहरण जारी रहता है। उदाहरण के लिए:

public class Widget 
{ 
    /// <summary> 
    /// This property is ignored by the NHibernate mappings. 
    /// </summary> 
    public virtual WidgetTest WidgetTest { get; set; } 

    /// <summary> 
    /// For easier persistence with NHibernate, this property repackages the 
    /// WidgetTest property as a list containing a single item. If an 
    /// attempt is made to set this property to a list containing more than 
    /// one item, an exception will be thrown. But why bother? Just use the 
    /// WidgetTest property. 
    /// </summary> 
    public virtual IList<WidgetTest> WidgetTests 
    { 
     get 
     { 
      IList<WidgetTest> widgetTests = new List<WidgetTest>(); 
      if (this.WidgetTest != null) 
      { 
       widgetTests.Add(this.WidgetTest); 
      } 
      return widgetTests; 
     } 
     set 
     { 
      if (value != null && value.Count > 1) 
      { 
       throw new Exception("The WidgetTests collection may not contain more than one item."); 
      } 
      else if (value != null && value.Count == 1) 
      { 
       this.WidgetTest = value[0]; 
      } 
      else 
      { 
       this.WidgetTest = null; 
      } 
     } 
    } 
} 
+0

यह मेरे "मॉडल 2" से कम या कम है और मैंने अतीत में कुछ ऐसा ही किया है। मैं संग्रह को एक निजी सदस्य के रूप में मानचित्रित करता हूं और हालांकि इसका खुलासा नहीं करता हूं। मैं इसके बारे में थोड़ा और सोच रहा था और यह मॉडल 1: एन रिश्ते के लिए काम करता है। जब मैं एन = 1 पर लटका रहा हूं। –

+0

मेरे द्वारा सुलझाने वाले समाधान के लिए मेरे प्रश्न में संपादन देखें। यह जवाब निकटतम है इसलिए मैंने इसे स्वीकार कर लिया। –

+0

मुझे आपकी विविधता पसंद है ... बहुत संक्षेप में। क्या आप एनएच मैपिंग का इस्तेमाल करने के इच्छुक होंगे? –

1

जब आप कहते हैं कि "मानते हैं कि यह विजेट WidgetTest फ़ील्ड्स जोड़ने के लिए अनुचित है", आप अपने डोमेन वस्तुओं में या डेटाबेस में मतलब है । यदि आप डेटाबेस में एक ही तालिका में फ़ील्ड के लिए खुश हैं, तो विजेट के घटक के रूप में विजेटटेस्ट को मैप करने के बारे में कैसे?

<class name="Widget" table="Widget"> 
    ... 
    <property name="WidgetProperty"/> 
    ... 
    <component name="WidgetTest" class="WidgetTest"> 
     <property name="WidgetTestProperty"/> 
    </component> 
</class> 

तालिका संरचना देते: की तरह NHibernate मैपिंग फ़ाइल नज़र

WidgetTable 
    WidgetProperty 
    WidgetTestProperty 

कौन सा अभी भी आप सार्वजनिक इंटरफ़ेस आपके द्वारा निर्दिष्ट राशि देना होगा, फिर भी, WidgetTest एक मूल्य वस्तु बन जाएगा जो आप चाहें या नहीं चाहें

+0

मेरा मतलब है टेबल में। एक सौ अतिरिक्त फ़ील्ड जोड़ने के अलावा, उन्हें अनावश्यक रूप से शून्य करना होगा जो अवांछित है। मैं एक विशिष्ट आवेदन के मुकाबले आम तौर पर 1: 0,1 रिश्तों को मॉडल करने का सबसे अच्छा तरीका हूं। –

0

मैं 2 अन्य विचारों here

  • तालिका में शामिल हों और घटक के रूप में नक्शा
  • निर्भर वर्ग की पहचान की अनदेखी
0

answer given by nw. अपवाद में परिणाम कर सकते हैं " A collection with cascade=”all-delete-orphan” was no longer referenced by the owning entity instance "।

यदि आप inverse="true" और cascade="all-delete-orphan" का उपयोग अपनी मैपिंग फ़ाइल में कर रहे हैं तो आपको यह मामला मिल जाएगा।

ऐसा इसलिए है क्योंकि nw। का उत्तर हर बार get एक्सेसर कहलाता है और set एक्सेसर के माध्यम से पारित सूची के साथ कुछ भी नहीं करता है। इस प्रकार, NHibernate में IList<WidgetTest> संदर्भ नहीं है जो मूल रूप से ऑब्जेक्ट बनाते समय पारित होता है और कैस्केड के साथ आगे नहीं बढ़ सकता है।

तो इसे ठीक करने के लिए, हमें IList<WidgetTest> संदर्भ के साथ कुछ करने की आवश्यकता है और सावधान रहें कि इसे संदर्भित न करें।

public class Widget 
{ 
    public Widget() 
    { 
     _widgetTests = new List<WidgetTest>(); 
    } 

    /// <summary> 
    /// This property is ignored by the NHibernate mappings. 
    /// </summary> 
    public WidgetTest WidgetTest { get; set; } 

    /// <summary> 
    /// For easier persistence with NHibernate, this property repackages the 
    /// WidgetTest property as a list containing a single item. If an 
    /// attempt is made to set this property to a list containing more than 
    /// one item, an exception will be thrown. But why bother? Just use the 
    /// WidgetTest property. 
    /// </summary> 
    private IList<WidgetTest> _widgetTests; 
    protected virtual IList<WidgetTest> WidgetTests 
    { 
     get 
     { 
      if (_widgetTests.Count == 0 && WidgetTest != null) 
      { 
       _widgetTests.Add(WidgetTest); 
      } 
      else if (_widgetTests.Count > 0 && WidgetTest == null) 
      { 
       _widgetTests.Clear(); 
      } 
      else if (_widgetTests.Count > 0 && WidgetTest != _widgetTests[0]) 
      { 
       _widgetTests.Clear(); 
       _widgetTests.Add(WidgetTest); 
      } 
      return _widgetTests; 
     } 
     set 
     { 
      if (value != null && value.Count > 1) 
      { 
       throw new Exception("The WidgetTest collection may not contain more than one item."); 
      } 
      if (value != null && value.Count == 1) 
      { 
       WidgetTest = value[0]; 
      } 
      else 
      { 
       WidgetTest = null; 
      } 

      //Store the reference 
      _widgetTests = value; 
     } 
    } 
} 

मैपिंग: बढ़ाने के लिए

<class name="Widget" table="widgets"> 
    ... 
    <id name="Id" type="Guid" column="widgetId"> 
     ... 
    </id> 
    ...     
    <bag name="WidgetTests" inverse="true" cascade="all-delete-orphan" access="property"> 
     ... 
     <key column="widgetId" /> 
     <one-to-many class="WidgetTest" /> 
    </bag> 

    </class> 

प्रेरणा:

http://www.onkarjoshi.com/blog/188/hibernateexception-a-collection-with-cascade-all-delete-orphan-was-no-longer-referenced-by-the-owning-entity-instance/comment-page-1/

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