2012-09-03 35 views
2

後,我有一個類DepartmentEntity,包括一個名爲Company(CompanyEntity)爲波紋管的特性:不能訪問引用對象的會話關閉

public class DepartmentEntity 
{ 
    public virtual int ID { get; set; } 
    public virtual string Name { get; set; } 
    public virtual DepartmentEntity Parent { get; set; } 
    public virtual CompanyEntity Company { get; set; } 
} 

public class CompanyEntity 
{ 
    public virtual int ID { get; set; } 
    public virtual string Name { get; set; } 
} 

DepartmentEntity.hbm.xml波紋管:

<?xml version="1.0" encoding="utf-8" ?> 
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> 
     <class name="HS.DepartmentEntity, HS" table="DepartmentInfo" lazy="true"> 
      <id name="ID"> 
       <generator class="identity" /> 
      </id> 
      <property name="Name" not-null="true" /> 
      <many-to-one name="Parent" column="ParentID" class="HS.DepartmentEntity, HS" cascade="none" unique="true" not-found="ignore" lazy="no-proxy" /> 
      <many-to-one name="Company" column="CompanyID" class="HS.CompanyEntity, HS" cascade="none" unique="true" not-found="ignore" lazy="no-proxy" /> 
     </class> 
    </hibernate-mapping> 

CompanyEntity.hbm.xml波紋管:

<?xml version="1.0" encoding="utf-8" ?> 
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> 
     <class name="HS.CompanyEntity, HS" table="CompanyInfo" lazy="true"> 
      <id name="ID"> 
       <generator class="identity" /> 
      </id> 
      <property name="Name" not-null="true" /> 
     </class> 
    </hibernate-mapping> 

我試了下面的代碼:

IList<DepartmentEntity> list; 
using(ISession session = GetSession()) 
{ 
    string hql = "FROM DepartmentEntity as dpe join fetch dpe.Company"; 
    list = session.CreateQuery(hql).List<DepartmentEntity>(); 
} 

會議閉幕後,房地產Company無法訪問,但如果該列表方法只發現一個記錄,財產Company可以被訪問,我不知道爲什麼。

+0

通過'我有一個對象',我假設你的意思是'我寫了一個叫''的類。 「訪問」是什麼意思?你的意思是訪問?如果是這樣的話,我假設你在運行時訪問它時遇到了問題,並且你應該得到一個異常,你可以跟蹤它以更好地瞭解發生了什麼問題。你能否向我們展示'DepartmentEntity'類和'Company(CompanyEntity)' - 屬性的相關部分(即使我不知道其他屬性,參數,索引屬性)? –

+1

缺少異常詳情。 –

+0

@Aske B,我更新了代碼,FYI。 –

回答

0

NHibernate使用會話對象來延遲加載導航屬性。當你第一次訪問導航屬性時,NHibernate訪問數據存儲並使用會話獲取對象的值。當會話關閉時,嘗試訪問該屬性將引發NHibernate.LazyInitializationException類型的異常。

我建議您儘量保持會話打開,同時需要訪問公司屬性,或者您可以關閉應用程序的延遲加載(這可能會降低性能)。

0

我假設你的問題是關閉會話後,你正在嘗試加載一個懶惰的屬性。 所以你可以做某事像這樣:

if(!NHibernateUtil.IsInitialized(object.Lazy_property)) 

     NHibernateUtil.Initialize(object.Lazy_property); 

它會拋出一個異常「收藏不與任何會話相關的」,所以你必須打開一個會話,對象通常添加到會話(我使用session.saveorUpdate(object)),然後初始化lazy屬性。

if(!NHibernateUtil.IsInitialized(object.Lazy_property)) 

{

  //open a session 
     session.SaveorUpdate(object); 
     NHibernateUtil.Initialize(object.Lazy_property); 
     //close the session 

}

你仍然可以得到一個異常「與相同ID的另一個實例是會議」所以你必須檢查是否有相同的另一個實例ID在會話中。如果你通過不同的文檔,他們建議你在將對象添加到會話之前檢查session.contains(object)。

if(!NHibernateUtil.IsInitialized(object.Lazy_property)) 

{

  //open a session 
     if (session.Contains(object)) 
      session.evict(object); 
     Session.SaveorUpdate(object); 
     NHibernateUtil.Initialize(object.Lazy_property); 
     //close the session 

}

它仍然沒有解決問題。因爲包含方法不在ID上的實例。所以一個好的方法是使用Load方法:

if (!NHibernateUtil.IsInitialized(object.Lazy_property)) 
    { 
     //open a session 
     Class1 temp_object= lSession.Load<Class1>(object.ID); 
     if (temp_object.ID == Object.ID) 
      Session.Evict(lProgressItemType); 

     Session.SaveOrUpdate(this); 
     NHibernateUtil.Initialize(ProxyMilestoneList); 
     //close session 
     } 

,最好的方法是使用負載和包含在一起:

if (!NHibernateUtil.IsInitialized(object.Lazy_property)) 
    { 
     //open a session 
     Class1 temp_object= lSession.Load<Class1>(object.ID); 
     if (temp_object.ID == object.ID && !Session.Contain(object)) 
      Session.Evict(lProgressItemType); 

     Session.SaveOrUpdate(this); 
     NHibernateUtil.Initialize(ProxyMilestoneList); 
     //close session 
     } 

因爲剛剛通過檢查ID,有可能你刪除實例您想要從會話開始處理它,然後再將它添加到會話中。它不會拋出任何異常,但是你打了兩次DB。