2009-11-09 16 views
6

मेरे पास दो संबंधित व्यावसायिक ऑब्जेक्ट्स हैं - ए और बी एसोसिएशन (ए-> बी) बी-डी के साथ कई-से-एक है ए में विदेशी कुंजी (इसलिए ए में डीबी में एबी_आईडी है)।NHibernate - पूरे ऑब्जेक्ट को आलसी लोड किए बिना किसी संबंधित ऑब्जेक्ट की आईडी तक पहुंचें

मैं आलसी = सत्य का उपयोग कर रहा हूं और मेरी अधिकांश समस्याओं का समाधान कर रहा हूं, हालांकि ए के टूस्ट्रिंग में मैं एबीआईआईडी भी प्रिंट करना चाहता हूं, जो मुझे डीबी के आगे और यात्रा के बिना होना चाहिए। लेकिन एबी तक पहुंच प्रॉक्सी को सक्रिय करती है, और चूंकि यह एक खुले सत्र के संदर्भ में नहीं है, अपवाद फेंकता है।

एक आसान लेकिन बदसूरत समाधान एबी_आईडी संपत्ति होगी। लेकिन वह सामान है जो हम पहले स्थान से बचने की कोशिश कर रहे थे। ऐसा करने के लिए कोई "जैविक" तरीका? :) धन्यवाद!


अपडेट: बस कैशिंग और सत्र के बारे में पढ़ें। बनाम सत्र। लोड करें। इससे पहले कि मैं केवल नया हूं कि कोई अपवाद फेंकता है यदि ऑब्जेक्ट मौजूद नहीं है (सत्र। लोड), और दूसरा एक शून्य ऑब्जेक्ट (सत्र.गेट) देता है। here कैशिंग के बारे में पढ़ने के बाद, यह स्पष्ट है कि सत्र। लोड ऑब्जेक्ट को प्रॉक्सी देता है, और केवल आलसी रूप से इसे प्राप्त करता है जब आईडी के अलावा किसी अन्य संपत्ति का उपयोग किया जाता है, जो कि एसोसिएशन से मुझे बहुत कुछ चाहिए! अब के लिए मैंने अलग ऑब्जेक्ट आईडी जोड़ दी हैं (एबीआई को जोड़ने के बजाय इसे एबी_आईडी के रूप में एक्सेस किया जा सकता है)

+0

आप ऐसा क्यों करना चाहते हैं? – Paco

+0

जैसा कि मैंने कहा था, सिर्फ लॉग प्रिंटिंग आदि के लिए, ए के ToString() में। मुझे बस आईडी से अन्य क्षेत्रों की आवश्यकता नहीं है। –

उत्तर

3

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

मेरे मानचित्रण फ़ाइलें useually इस तरह दिखेगा:

<property name="CreatorID" column="CreatorID" type="Int32" not-null="true" /> 
<many-to-one name="Creator" column="CreatorID" class="SystemUser" insert="false" update="false" cascade="none" /> 

आप 2 संपत्ति में से एक देख सकते हैं NHibernate डेटाबेस जब प्रविष्ट करता है या updatas हैं 2 बार इस कॉलम भेजने से बचने के लिए केवल पढ़ने के लिए किया जाना है हो रहा। उपर्युक्त केवल पढ़ने के लिए बनाता है (सम्मिलित = "झूठी" अद्यतन = "झूठी" विशेषताओं का उपयोग करके) कई से एक लेकिन आप चाहें तो केवल निर्माता आईडी प्रॉपर्टी को पढ़ सकते हैं।

केवल एक से अधिक होने के कारण आपके पास बीआईडी ​​मान रखने के लिए आपकी इकाई श्रेणी ए में कोई संपत्ति नहीं है। इसे प्राप्त करने का एकमात्र तरीका बी ऑब्जेक्ट तक पहुंचने से है जो प्रॉक्सी को ट्रिगर करेगा और यह डेटाबेस को एक क्वेरी आग देगा (यदि यह पहले से ही सत्र में लोड नहीं होता है)।

मुझे कोई अन्य विकल्प सुनने में खुशी होगी जो समाधान प्रदान करता है और उसी तरह की लचीलापन प्रदान करता है।

using NHibernate.Proxy; 
... 
object id = null; 
if (obj.IsProxy()) // obj is the object you want to get its identifier. 
{ 
    var proxy = obj as INHibernateProxy; 
    if (proxy != null) 
    { 
     var li = proxy.HibernateLazyInitializer; 
     if (li != null) 
      id = li.Identifier; 
    } 
} 
+0

मुझे अभी भी यह एबीआईडी ​​का उपयोग करके किया जा सकता है - मुझे डुप्लिकेट डेटा पसंद नहीं है - मेरे पास ये गुण थे और * उन्हें हटा दिया गया ... मैं इस मामले की और जांच करूँगा लेकिन अभी के लिए मैं यही करूंगा । धन्यवाद! –

+0

@ योनातनकर्णी पूरी तरह से सहमत हैं। इसके साथ एक प्रमुख प्रदर्शन मुद्दा भी है। एक संस्था संग्रह (एक सेट बैकिंग प्रकार के साथ) में 'प्रॉक्सी' इकाइयों की एक बड़ी संख्या, एन, जोड़ें, और यह प्रदर्शन को मारता है, क्योंकि एन चयन, एक प्रति प्रॉक्सी, अनुक्रमिक रूप से किया जाता है, क्योंकि 'set.Add' करता है' चीज़। – jasper

5

आप NHibernate 3.2 या बाद का उपयोग कर रहे हैं, तो आप निम्न कोड जुड़े वस्तु की आईडी प्राप्त करने के लिए एक और गोल यात्रा के बिना डेटाबेस के लिए पूरी वस्तु लोड करने के लिए इस्तेमाल कर सकते हैं निबर्ननेट सत्र:

session.GetIdentifier(obj); 
1

आप की GetIdentifier विधि का उपयोग कर सकते हैं:

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