2010-06-23 32 views
5

Tôi đang sử dụng nHibernate 2.1.2 và relized rằng nhibernate sẽ tạo ra bên ngoài bên ngoài tham gia vào lồng nhau nhiều-một thực thể. có vẻ như bắt đầu tạo ra bên ngoài-tham gia bên ngoài trên lưu ý lồng nhau thứ 3 trở đi bắt đầu từ tổ chức thực thể. tôi đã đặt sau trong tập tin bản đồ để buộc sử dụng bên trong tham gia, có bất cứ điều gì tôi bỏ lỡ trong tập tin bản đồ? thực sự hy vọng ai đó có thể cho tôi một gợi ý về điều này. đánh giá cao bất kỳ giúp!nhibernate tạo ra bên ngoài tham gia bên ngoài trên nhiều-to-một thực thể

lazy="false" fetch="join" 

Ví dụ entites và mối quan hệ: Sales Ghi - nhân viên - Tổ chức

nhibernate generate:

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

Truy vấn trông như thế nào? Bạn đang sử dụng HQL hoặc tiêu chuẩn? –

+0

tôi chỉ làm Entity.Fetch, btw tôi thử nghiệm với HQL quá và cùng một vấn đề. – ksang

+0

tôi đã khắc phục vấn đề này bằng cách sửa đổi nguồn nhibernate, tôi phát hiện ra rằng nhibernate sẽ chỉ tạo ra innerjoint sql cho cấp đầu tiên của tham gia. có lẽ ai đó có thể cho tôi biết tại sao hành vi của nó theo cách đó. – ksang

Trả lời

4

Nếu NHibernate làm một bên tham gia bạn không ID từ một đứa trẻ và ID từ một bảng cha (nhưng chúng giống nhau).

Ví dụ:

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

Nếu nHibernate làm một bên tham gia, bạn nhận được:

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

Nếu nHibernate làm một phép nối ngoài trái tham gia, bạn nhận được:

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

Và bởi vì của các hoạt động bên trong của NHibernate nó sau đó có thể tạo ra 2 thực thể từ truy vấn thứ hai. Một thực thể cho TableChild và một cho TableParent.

Trong truy vấn đầu tiên bạn chỉ nhận được thực thể TableChild và trong một số trường hợp, p.Name sẽ bị bỏ qua (probalby ở cấp thứ hai) và nó sẽ yêu cầu cơ sở dữ liệu kiểm tra thuộc tính tham chiếu TableParent.

tôi phát hiện ra điều này khi tôi muốn tải một cấu trúc cây chỉ với một hit cơ sở dữ liệu:

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(); 
     } 
    } 
} 

Và truy vấn tôi đã sử dụng được điều này:

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(); 

Với NHibernate.SqlCommand .JoinType.LeftOuterJoin. Bởi vì nếu tôi sử dụng InnerJoin cấu trúc không tải chỉ với một truy vấn. Tôi đã phải sử dụng LeftOuterJoin, để NHibernate nhận ra các thực thể.

SQL Queries mà thực hiện là:

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 

hợp truy vấn đầu tiên còn lại bên ngoài tham gia và chúng tôi nhận được 2 trường bổ sung: t1_.id_SysPermissionTree_Parent như id4_4_, t1_.ID như ID4_

Vì vậy, những gì tôi 'm cố gắng để nói với bạn là nếu bạn sử dụng NHibernate sau đó bên ngoài tham gia bên ngoài đôi khi phải tuân thủ các hoạt động bên trong của NHibernate.

Các vấn đề liên quan