2010-06-23 10 views
5

मैं nHibernate 2.1.2 का उपयोग कर रहा हूं और यह स्वीकार करता हूं कि निबर्ननेट ने कई से अधिक इकाइयों पर बाएं बाहरी जुड़ने का उत्पादन किया है। ऐसा लगता है कि तीसरे नेस्टेड नोट पर बाएं-बाहरी-जुड़ाव उत्पन्न होता है जो इकाई संगठन से शुरू होता है। मैंने मैपिंग फ़ाइल में निम्नलिखित शामिल किया है ताकि आंतरिक-जुड़ने के उपयोग को मजबूर किया जा सके, क्या मैपिंग फ़ाइल में मुझे कुछ भी याद आया है? वास्तव में उम्मीद है कि कोई मुझे इस पर एक संकेत दे सकता है। किसी भी मदद की सराहना करते हैं!निबर्ननेट कई से एक इकाई पर बाएं बाहरी जुड़ने का उत्पादन करता है

lazy="false" fetch="join" 

उदाहरण entites और रिश्ते: बिक्री रिकार्ड - कर्मचारी - संगठन

nhibernate उत्पन्न:

select... 
from sales 
inner join employee 
left outer join organization 

Sales.hbm.xml

<many-to-one name="Employee" insert="true" update="true" access="field.pascalcase-underscore" not-null="true" lazy="false" fetch="join"/> 
<column name="EmployeeId" not-null="true"/> 
</many-to-one> 

Employee.hbm.xml

<many-to-one name="Organization" insert="true" update="true" access="field.pascalcase-underscore" not-null="true" lazy="false" fetch="join"/> 
<column name="OrgId" not-null="true"/> 
</many-to-one> 
+1

क्वेरी कैसा दिखता है? क्या आप एचक्यूएल या मानदंड का उपयोग कर रहे हैं? –

+0

मैं सिर्फ Entity.Fetch करता हूं, btw मैंने एचक्यूएल के साथ भी परीक्षण किया है और एक ही समस्या है। – ksang

+0

मैंने संशोधित निबर्ननेट स्रोत द्वारा इस समस्या को ठीक कर दिया है, मुझे पता चला है कि निबर्ननेट केवल जुड़ने के पहले स्तर के लिए आंतरिकज एसक्यूएल उत्पन्न करेगा। शायद कोई मुझे बता सकता है कि ऐसा क्यों व्यवहार करता है। – ksang

उत्तर

4

NHibernate एक आंतरिक करता है कि आप एक बच्चे और एक माता पिता मेज से आईडी से आईडी नहीं है (लेकिन वे एक ही कर रहे हैं) में शामिल हो।

उदाहरण:

TableParent (ID, Name) 
    TableChild (ID, ID_TableParent, ....) 

nHibernate एक आंतरिक में शामिल होता है, तो आप प्राप्त करें:

select c.ID, c.ID_TableParent, p.Name 
from TableChild c 
inner join TableParent p on p.ID = c.ID_TableParent 

nHibernate एक बाईं बाहरी में शामिल होता है, तो आप प्राप्त करें:

select c.ID, c.ID_TableParent, p.ID, p.Name 
from TableChild c 
left outer join TableParent p on p.ID = c.ID_TableParent 

और क्योंकि NHibernate की आंतरिक कार्यप्रणाली के बाद यह दूसरी क्वेरी से 2 इकाइयां बना सकती है। TableChild के लिए एक इकाई और TableParent के लिए एक इकाई।

पहली क्वेरी में आपको केवल टेबलChild इकाई मिल जाएगी और कुछ मामलों में p.Name को अनदेखा किया जाएगा (दूसरे स्तर पर probalby) और यह तालिका को संदर्भित करने वाली संपत्ति की जांच करने के लिए डेटाबेस की आवश्यकता होगी।

मैं इस में पता चला जब मैं डेटाबेस के लिए केवल एक हिट के साथ एक वृक्ष संरचना लोड करने के लिए चाहता था: NHibernate.SqlCommand साथ

SysPermissionTree t = null; 
SysPermission p = null; 

return db.QueryOver<SysPermissionTree>() 
     .JoinAlias(x => x.Children,() => t, NHibernate.SqlCommand.JoinType.LeftOuterJoin) 
     .JoinAlias(() => t.Permissions,() => p, NHibernate.SqlCommand.JoinType.LeftOuterJoin) 
     .Where(x => x.Parent == null) 
     .TransformUsing(Transformers.DistinctRootEntity) 
     .List(); 

:

public class SysPermissionTree 
{ 
    public virtual int ID { get; set; } 
    public virtual SysPermissionTree Parent { get; set; } 
    public virtual string Name_L1 { get; set; } 
    public virtual string Name_L2 { get; set; } 

    public virtual Iesi.Collections.Generic.ISet<SysPermissionTree> Children { get; private set; } 
    public virtual Iesi.Collections.Generic.ISet<SysPermission> Permissions { get; private set; } 

    public class SysPermissionTree_Map : ClassMap<SysPermissionTree> 
    { 
     public SysPermissionTree_Map() 
     { 
      Id(x => x.ID).GeneratedBy.Identity(); 

      References(x => x.Parent, "id_SysPermissionTree_Parent"); 
      Map(x => x.Name_L1); 
      Map(x => x.Name_L2); 
      HasMany(x => x.Children).KeyColumn("id_SysPermissionTree_Parent").AsSet(); 
      HasMany(x => x.Permissions).KeyColumn("id_SysPermissionTree").AsSet(); 
     } 
    } 
} 

और क्वेरी मैं इस्तेमाल किया यह था .JoinType.LeftOuterJoin। क्योंकि अगर मैंने इनरजॉइन का उपयोग किया था तो संरचना केवल एक क्वेरी के साथ लोड नहीं हुई थी। मुझे LeftOuterJoin का उपयोग करना पड़ा, ताकि एनएचबेर्नेट ने इकाइयों को पहचाना।

एसक्यूएल क्वेरी जो निष्पादित किए गए:

SELECT this_.ID as ID28_2_, this_.Name_L1 as Name2_28_2_, this_.Name_L2 as Name3_28_2_, this_.id_SysPermissionTree_Parent as id4_28_2_, t1_.id_SysPermissionTree_Parent as id4_4_, t1_.ID as ID4_, t1_.ID as ID28_0_, t1_.Name_L1 as Name2_28_0_, t1_.Name_L2 as Name3_28_0_, t1_.id_SysPermissionTree_Parent as id4_28_0_, p2_.id_SysPermissionTree as id4_5_, p2_.ID as ID5_, p2_.ID as ID27_1_, p2_.Name_L1 as Name2_27_1_, p2_.Name_L2 as Name3_27_1_, p2_.id_SysPermissionTree as id4_27_1_ FROM [SysPermissionTree] this_ left outer join [SysPermissionTree] t1_ on this_.ID=t1_.id_SysPermissionTree_Parent left outer join [SysPermission] p2_ on t1_.ID=p2_.id_SysPermissionTree WHERE this_.id_SysPermissionTree_Parent is null 
SELECT this_.ID as ID28_2_, this_.Name_L1 as Name2_28_2_, this_.Name_L2 as Name3_28_2_, this_.id_SysPermissionTree_Parent as id4_28_2_, t1_.ID as ID28_0_, t1_.Name_L1 as Name2_28_0_, t1_.Name_L2 as Name3_28_0_, t1_.id_SysPermissionTree_Parent as id4_28_0_, p2_.ID as ID27_1_, p2_.Name_L1 as Name2_27_1_, p2_.Name_L2 as Name3_27_1_, p2_.id_SysPermissionTree as id4_27_1_ FROM [SysPermissionTree] this_ inner join [SysPermissionTree] t1_ on this_.ID=t1_.id_SysPermissionTree_Parent inner join [SysPermission] p2_ on t1_.ID=p2_.id_SysPermissionTree WHERE this_.id_SysPermissionTree_Parent is null 

जहां पहली क्वेरी बाहरी छोड़ दिया है में शामिल होने और हम 2 अतिरिक्त क्षेत्रों मिलती है: ID4_

रूप id4_4_ रूप t1_.ID t1_.id_SysPermissionTree_Parent, तो क्या मैं मैं आपको यह बताने की कोशिश कर रहा हूं कि यदि आप एनएचबीर्नेट का उपयोग करते हैं तो बाहरी बहिष्कार को कभी-कभी एनएचबर्ननेट के आंतरिक कार्यों का अनुपालन करना आवश्यक होता है।

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

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