2010-06-23 15 views
5

Używam nHibernate 2.1.2 i relizuję, że nhibernate wygeneruje lewe sprzężenie zewnętrzne na zagnieżdżonych wiele-do-jednego. wygląda na to, że zacznij generować lewostronne sprzężenie na trzeciej zagnieżdżonej notatce, która rozpoczyna się od elementu Organization. ustawiłem następujące w pliku odwzorowania, aby wymusić użycie wewnętrznego łączenia, czy coś brakuje mi w pliku odwzorowania? naprawdę mam nadzieję, że ktoś mógłby mi o tym powiedzieć. doceniamy każdą pomoc!nhibernate generuje lewe sprzężenie zewnętrzne w jednostce wiele do jednego

lazy="false" fetch="join" 

Przykład udziałów w jednostkach i zależności: sprzedaży płyt - Pracownik - organizację

NHibernate generują:

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

Jak wygląda zapytanie? Czy używasz HQL lub kryteriów? –

+0

Po prostu robię Entity.Fetch, przy okazji testowałem także z HQL i tym samym problemem. – ksang

+0

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

Odpowiedz

4

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.

Powiązane problemy