Jeśli NHibernate robi sprzężenie wewnętrzne nie masz identyfikatora od dziecka i ID z tabeli nadrzędnej (ale są takie same).
Przykład:
TableParent (ID, Name)
TableChild (ID, ID_TableParent, ....)
Jeśli nHibernate robi sprzężenie wewnętrzne, otrzymasz:
select c.ID, c.ID_TableParent, p.Name
from TableChild c
inner join TableParent p on p.ID = c.ID_TableParent
Jeśli nHibernate odpowiada dana lewe sprzężenie zewnętrzne, można uzyskać:
select c.ID, c.ID_TableParent, p.ID, p.Name
from TableChild c
left outer join TableParent p on p.ID = c.ID_TableParent
a ponieważ z wewnętrznego działania NHibernate może następnie utworzyć 2 elementy z drugiego zapytania. Jeden podmiot dla TableChild i jeden dla TableParent.
W pierwszym zapytaniu otrzymasz tylko encję TableChild, aw niektórych przypadkach p.Nazwa zostanie zignorowana (probalby na drugim poziomie) i zażąda bazy danych podczas sprawdzania właściwości odwołującej się do TableParent.
I okazało się to, kiedy chciałam załadować strukturę drzewa z tylko jednym trafieniem do bazy danych:
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();
}
}
}
a zapytanie kiedyś było to:
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();
Z NHibernate.SqlCommand .JoinType.LeftOuterJoin. Ponieważ jeśli użyłem InnerJoin, struktura nie załadowała się tylko z jednym zapytaniem. Musiałem użyć LeftOuterJoin, aby NHibernate rozpoznał te obiekty.
zapytań SQL, które wykonywane były:
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
gdzie pierwsze zapytanie pozostało sprzężenie zewnętrzne i mamy 2 dodatkowe pola: t1_.id_SysPermissionTree_Parent jak id4_4_, t1_.ID jak ID4_
Więc co ja Próbuję ci powiedzieć, że jeśli używasz NHibernate, to lewe sprzężenie zewnętrzne jest czasem koniecznym do spełnienia wewnętrznych funkcji NHibernate.
Jak wygląda zapytanie? Czy używasz HQL lub kryteriów? –
Po prostu robię Entity.Fetch, przy okazji testowałem także z HQL i tym samym problemem. – ksang
Naprawiłem ten problem przez zmodyfikowane źródło nhibernate, dowiedziałem się, że nhibernate wygeneruje tylko wewnętrzny sql dla pierwszego poziomu sprzężenia. może ktoś mógłby mi powiedzieć, dlaczego tak się zachowuje. – ksang