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, तो क्या मैं मैं आपको यह बताने की कोशिश कर रहा हूं कि यदि आप एनएचबीर्नेट का उपयोग करते हैं तो बाहरी बहिष्कार को कभी-कभी एनएचबर्ननेट के आंतरिक कार्यों का अनुपालन करना आवश्यक होता है।
क्वेरी कैसा दिखता है? क्या आप एचक्यूएल या मानदंड का उपयोग कर रहे हैं? –
मैं सिर्फ Entity.Fetch करता हूं, btw मैंने एचक्यूएल के साथ भी परीक्षण किया है और एक ही समस्या है। – ksang
मैंने संशोधित निबर्ननेट स्रोत द्वारा इस समस्या को ठीक कर दिया है, मुझे पता चला है कि निबर्ननेट केवल जुड़ने के पहले स्तर के लिए आंतरिकज एसक्यूएल उत्पन्न करेगा। शायद कोई मुझे बता सकता है कि ऐसा क्यों व्यवहार करता है। – ksang