C# 会话关闭后无法访问引用的对象

C# 会话关闭后无法访问引用的对象,c#,nhibernate,C#,Nhibernate,我有一个类部门实体,包括一个名为公司(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

我有一个类
部门实体
,包括一个名为
公司(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; }
}
<?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>
<?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>
DepartmentEntity.hbm.xml
如下所示:

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; }
}
<?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>
<?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>(); 
} 
IList列表;
使用(ISession session=GetSession())
{ 
string hql=“作为dpe加入获取dpe.Company的部门实体”;
list=session.CreateQuery(hql.list();
} 

会话关闭后,无法访问属性
Company
,但如果列表方法仅找到一条记录,则可以访问属性
Company
,我不知道原因。

NHibernate使用会话对象延迟加载导航属性。当您第一次访问navigation属性时,NHibernate访问数据存储并使用会话获取对象的值。会话关闭时,尝试访问该属性会引发类型为
NHibernate.LazyInitializationException
的异常


我建议您在需要访问公司属性时尽量保持会话打开,或者您可以关闭应用程序的延迟加载(这可能会降低性能)。

NHibernate使用会话对象延迟加载导航属性。当您第一次访问navigation属性时,NHibernate访问数据存储并使用会话获取对象的值。会话关闭时,尝试访问该属性会引发类型为
NHibernate.LazyInitializationException
的异常


我建议您在需要访问Company属性时保持会话打开,或者您可以关闭应用程序的延迟加载(这可能会降低性能)。

我假设您的问题是在关闭会话后,您正在尝试加载延迟属性。 所以你可以这样做:

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

         NHibernateUtil.Initialize(object.Lazy_property);
但是它会抛出一个异常,即“集合与任何会话都不关联”,因此您必须打开一个会话,将对象添加到会话中(我通常使用session.saveorUpdate(object)),然后初始化lazy属性

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

}

但是您仍然可以得到“另一个具有相同ID的实例正在会话中”的异常,因此您必须检查另一个具有相同ID的实例是否正在会话中。如果您浏览了不同的文档,他们建议您在将对象添加到会话之前检查session.contains(对象)

{

}

但它仍然不能解决问题。因为Contains方法在实例上工作,而不是在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_属性))
{
//开课
Class1 temp_object=lSession.Load(object.ID);
if(temp_object.ID==object.ID)
会话.逐出(lProgressItemType);
会话。保存或更新(本);
初始化(ProxyMilestoneList);
//闭门会议
}
最好的方法是同时使用Load和Contains:

  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
       }
if(!NHibernateUtil.IsInitialized(object.Lazy_属性))
{
//开课
Class1 temp_object=lSession.Load(object.ID);
if(temp_object.ID==object.ID&&!Session.Contain(object))
会话.逐出(lProgressItemType);
会话。保存或更新(本);
初始化(ProxyMilestoneList);
//闭门会议
}

因为只需检查ID,就可以从会话中删除要处理的实例,然后再将其添加到会话中。它不会引发任何异常,但您两次命中了数据库。

我假设您的问题是在关闭会话之后,您正在尝试加载一个惰性属性。 所以你可以这样做:

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

         NHibernateUtil.Initialize(object.Lazy_property);
但是它会抛出一个异常,即“集合与任何会话都不关联”,因此您必须打开一个会话,将对象添加到会话中(我通常使用session.saveorUpdate(object)),然后初始化lazy属性

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

}

但是您仍然可以得到“另一个具有相同ID的实例正在会话中”的异常,因此您必须检查另一个具有相同ID的实例是否正在会话中。如果您浏览了不同的文档,他们建议您在将对象添加到会话之前检查session.contains(对象)

{

}

但它仍然不能解决问题。因为Contains方法在实例上工作,而不是在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_属性))
{
//开课
Class1 temp_object=lSession.Load(object.ID);
if(temp_object.ID==object.ID)
会话.逐出(lProgressItemType);
会话。保存或更新(本);
初始化(ProxyMilestoneList);
//闭门会议
}
最好的方法是同时使用Load和Contains:

  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
       }
if(!NHibernateUtil.IsInitialized(object.Lazy_属性))
{
//开课
Class1 temp_object=lSession.Load(object.ID);
if(temp_object.ID==object.ID&&!Session.Contain(object))
会话.逐出(lProgressItemType);
会话。保存或更新(本);
初始化(ProxyMilestoneList);
//闭门会议
}

因为只需检查ID,就可以从会话中删除要处理的实例,然后再将其添加到会话中。它不会抛出任何异常,但您两次命中了DB。

我想您说的“我有一个对象”是指“我编写了一个名为”的类。你说的“拜访”是什么意思?你是说访问?如果是这样的话,我假设您在运行时访问它时遇到问题,您应该会得到一个异常,您可以跟踪它以更好地了解出了什么问题。您能给我们看一下
部门实体
-类和
公司(Com)的相关部分吗