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)的相关部分吗