NHibernate bir iç oluyorsa Bir üst tablosundan bir çocuk ve kimliğinden kimliğini yok (ama ikisi de bir) katıldı.
Örnek:
TableParent (ID, Name)
TableChild (ID, ID_TableParent, ....)
nHibernate bir iç birleşim yaparsa, elde edersiniz: nHibernate bir sol dış birleşim yaparsa
select c.ID, c.ID_TableParent, p.Name
from TableChild c
inner join TableParent p on p.ID = c.ID_TableParent
elde edersiniz:
select c.ID, c.ID_TableParent, p.ID, p.Name
from TableChild c
left outer join TableParent p on p.ID = c.ID_TableParent
Ve çünkü, NHibernate iç çalışmalarının ardından ikinci sorgudan 2 öğe oluşturabilir. TableChild ve TableParent için bir varlık.
İlk sorguda yalnızca TableChild öğesinin elde edilmesi ve bazı durumlarda p.Name (ikinci düzeyde probalby) göz ardı edilir ve TableParent'e başvuran özelliklerin kontrol edilmesinde veritabanı istenir. NHibernate.SqlCommand ile
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();
}
}
}
Ve kullandığım sorgusu şuydu: Ben veritabanına tek isabet ile bir ağaç yapısı yüklemek istediğinde
ben buldum .JoinType.LeftOuterJoin. Çünkü InnerJoin kullansaydım, yapı sadece bir sorguyla yüklenmedi. LeftOuterJoin'i kullanmam gerekti, böylece NHibernate varlıkları tanıdı. idam
SQL Sorguları idi:
İlk sorgu dış bırakılır
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
katılmak ve biz 2 ekstra alan almak: t1_.id_SysPermissionTree_Parent id4_4_ olarak, t1_.ID ID4_
olarak Yani ne Söylemeye çalışıyorum ki, eğer NHibernate kullanırsanız, dış birleşim, bazen NHibernate'in iç işleyişine uymak zorundadır.
Sorgu nasıl görünüyor? HQL veya kriterleri kullanıyor musunuz? –
Sadece Entity.Fetch yapıyorum, btw HQL de ve aynı sorun ile test ettik. – ksang
Bu sorunu modifiye nhibernate kaynağı tarafından düzelttim, nhibernate sadece ilk katma düzeyi için iç ortak sql üretecek olduğunu öğrendim. Belki birisi bana neden böyle davrandığını söyleyebilirdi. – ksang