2010-02-23 27 views
4

NHibernate的渴望獲取在多個級別,我引用下面的線程與會話,但不是StatelessSession工作。 NHibernate Eager Fetching Over Multiple Levels與StatelessSession

我遇到的問題是類似上述線程。我回來了4xApplications和4xRoles。我應該回來1xApplication和4xRoles。

條件查詢:

return StatelessSession.CreateCriteria(typeof(Application)) 
      .SetResultTransformer(Transformers.DistinctRootEntity) 
      .SetFetchMode("Roles", FetchMode.Join) 
      .List<Application>(); 

我的實體和映射:

public class Application : IComparable<Application> 
{ 
    public virtual int Id { get; set; } 
    public virtual string InternalName { get; set; } 
    public virtual ICollection<Role> Roles { get; set; } 

    #region IComparable<Application> Members 

    public virtual int CompareTo(Application other) 
    { 
     return Id.CompareTo(other.Id); 
    } 

    #endregion 

}

public class Role : IComparable<Role> 
{ 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual Application Application { get; set; } 

    public virtual int CompareTo(Role other) 
    { 
     return Id.CompareTo(other.Id); 
    } 

}

public class ApplicationMapping : ClassMap<Application> 
{ 
    public ApplicationMapping() 
    { 
     Table("Application"); 
     Id(x => x.Id, "ID").GeneratedBy.Assigned(); ; //.Column("ID"); 
     Map(x => x.InternalName); 
     HasMany(x => x.Roles).Inverse().Cascade.All().AsSet().Not.LazyLoad(); 
    } 
} 

public class RoleMapping : ClassMap<Role> 
{ 
    public RoleMapping() 
    { 

     Table("Roles"); 
     Id(x => x.Id, "ID").GeneratedBy.Assigned(); 
     References(x => x.Application, "ApplicationID").Not.LazyLoad(); 
     Map(x => x.Name); 
     HasMany(x => x.RightsUsers).Table("UserRoleXRef").Inverse().Cascade.All().AsSet(); 
    } 
} 

的hbm.xml

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property"  auto-import="true" default-cascade="none" default-lazy="true"> 
    <class xmlns="urn:nhibernate-mapping-2.2" name="Quad.App.Test.DataAccess.NHibernate.Scaffolding.Entities.Application, Quad.App.Test, Version=1.4.0.742, Culture=neutral, PublicKeyToken=null" table="Application"> 
<id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
    <column name="ID" /> 
    <generator class="assigned" /> 
</id> 
<property name="InternalName" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
    <column name="InternalName" /> 
</property> 
<set cascade="all" inverse="true" lazy="false" name="Roles"> 
    <key> 
    <column name="ApplicationID" /> 
    </key> 
    <one-to-many class="Quad.App.Test.DataAccess.NHibernate.Scaffolding.Entities.Role, Quad.App.Test, Version=1.4.0.742, Culture=neutral, PublicKeyToken=null" /> 
</set> 
    </class> 
</hibernate-mapping> 

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property"  auto-import="true" default-cascade="none" default-lazy="true"> 
    <class xmlns="urn:nhibernate-mapping-2.2" name="Quad.App.Test.DataAccess.NHibernate.Scaffolding.Entities.Role, Quad.App.Test, Version=1.4.0.742, Culture=neutral, PublicKeyToken=null" table="Roles"> 
<id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
    <column name="ID" /> 
    <generator class="assigned" /> 
</id> 
<property name="Name" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
    <column name="Name" /> 
</property> 
<many-to-one class="Quad.App.Test.DataAccess.NHibernate.Scaffolding.Entities.Application, Quad.App.Test, Version=1.4.0.742, Culture=neutral, PublicKeyToken=null" lazy="false" name="Application"> 
    <column name="ApplicationID" /> 
</many-to-one> 
    </class> 
</hibernate-mapping> 

SQL:

SELECT this_.ID as ID1_1_, 
this_.InternalName as Internal2_1_1_, 
roles2_.ApplicationID as Applicat3_3_, 
roles2_.ID as ID3_, 
roles2_.ID as ID2_0_, 
roles2_.Name as Name2_0_, 
roles2_.ApplicationID as Applicat3_2_0_ 
FROM dbo.Application this_ left outer join dbo.Roles roles2_ on  
this_.ID=roles2_.ApplicationID 
+0

怪異。你是否意識到你已經將角色映射爲非懶惰?我想知道FetchMode是否不喜歡被告知兩次?如果您刪除了SetFetchMode,它如何非懶惰地獲取角色?外部連接還是選擇? – dotjoe 2010-02-23 22:05:26

+0

然後我得到一個例外,你不能懶惰地加載角色列表。它只是從應用程序表中選擇。 SELECT this_.ID as ID1_0_,this_.InternalName as Internal2_1_0_ FROM dbo.Application this_ {「Initializing [Quad.App.Test.DataAccess.NHibernate.Scaffolding.Entities.Application#50] - 無法延遲初始化一個集合角色:Quad.App.Test.DataAccess.NHibernate.Scaffolding.Entities.Application.Roles,沒有會話或會話已關閉「} – magellings 2010-02-25 19:45:47

回答

0

我懷疑這是因爲SQL查詢生成產生重複的應用爲角色被加入。

避免這種情況的最簡單方法是使用ISet(HashedSet <>實現)而不是ICollection(在Iesi.Collections.dll中定義),它們的設計使您不會在列表中找到重複項。