Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用会话和延迟加载_C#_Nhibernate - Fatal编程技术网

C# 使用会话和延迟加载

C# 使用会话和延迟加载,c#,nhibernate,C#,Nhibernate,使用NHibernate和C#,我在删除使用属性惰性加载加载的对象时遇到问题 对象是 public class Item { public virtual Guid ItemID { get; set; } public virtual string Name { get; set; } public virtual decimal Price { get; set; } public virtual string Image { get; set; }

使用NHibernate和C#,我在删除使用属性惰性加载加载的对象时遇到问题

对象是

public class Item
{
    public virtual Guid ItemID { get; set; }    
    public virtual string Name { get; set; }
    public virtual decimal Price { get; set; }
    public virtual string Image { get; set; }
    public virtual Iesi.Collections.Generic.ISet<Tax> Taxes { get; set; }
}
我得到以下错误

非法尝试将集合与两个打开的会话关联

错误很明显,获取的对象已打开会话,当我打开另一个会话以删除同一对象时,会产生此错误


请有人指导我摆脱这个错误。谢谢。

错误在您的设计中。您正在打开一个会话以获取对象,并将其保持打开状态。然后,您将打开另一个会话以删除托管对象,但您打算自动关闭此会话。那么,为什么不使用
FindByID
方法关闭会话呢

您需要考虑您的设计,因为上面的内容不一致——或者正如Morten所说,提出一个更深入的问题(即应该如何设计)

因为您需要访问惰性实例,所以最好使用Morten的方法,或者根据web请求使用会话,或者通过设置自己的请求上下文(如果您没有创建web应用程序)来创建会话。如果您还没有基于上下文的设计,一种更简单的方法是在事件开始时创建会话(即用户希望删除一项),并将会话传递到DAO方法:

public Item FindByID(Session session, Guid itemID)
{
    using (var tr = session.BeginTransaction())
    {
        return session.Get<Item>(itemID);
    }
}

public void RemoveItem(Session session, Item item)
{
    using (var tr = session.BeginTransaction())
    {
         session.Delete(item);
         tr.Commit();
    }
}
公共项FindByID(会话会话,Guid itemID)
{
使用(var tr=session.BeginTransaction())
{
返回会话.Get(itemID);
}
}
公共无效删除项(会话,项目)
{
使用(var tr=session.BeginTransaction())
{
删除(项目);
tr.Commit();
}
}

您可以更进一步,在DAO之外创建事务,这将更快,并充分利用事务(即,稍后您可能会有通过通用DAO执行相互依赖的数据库操作的请求)。

错误在您的设计中。您正在打开一个会话以获取对象,并将其保持打开状态。然后,您将打开另一个会话以删除托管对象,但您打算自动关闭此会话。那么,为什么不使用
FindByID
方法关闭会话呢

您需要考虑您的设计,因为上面的内容不一致——或者正如Morten所说,提出一个更深入的问题(即应该如何设计)

因为您需要访问惰性实例,所以最好使用Morten的方法,或者根据web请求使用会话,或者通过设置自己的请求上下文(如果您没有创建web应用程序)来创建会话。如果您还没有基于上下文的设计,一种更简单的方法是在事件开始时创建会话(即用户希望删除一项),并将会话传递到DAO方法:

public Item FindByID(Session session, Guid itemID)
{
    using (var tr = session.BeginTransaction())
    {
        return session.Get<Item>(itemID);
    }
}

public void RemoveItem(Session session, Item item)
{
    using (var tr = session.BeginTransaction())
    {
         session.Delete(item);
         tr.Commit();
    }
}
公共项FindByID(会话会话,Guid itemID)
{
使用(var tr=session.BeginTransaction())
{
返回会话.Get(itemID);
}
}
公共无效删除项(会话,项目)
{
使用(var tr=session.BeginTransaction())
{
删除(项目);
tr.Commit();
}
}

您可以更进一步,在DAO之外创建事务,这将更快,并充分利用事务(即,稍后您可能会有通过通用DAO执行相互依赖的数据库操作的请求)。

您需要确保始终只有一个会话处于活动状态。有两种流行的方法:

  • 拥有一个始终将请求转发到的服务层。该服务层负责会话处理(和事务处理)。所有业务逻辑都必须在会话层中处理,以便始终拥有会话。您必须在UI中加载所需的所有内容,并将其作为响应的一部分返回。例如,有关使用nhibernate的简单请求-响应服务层,请参阅
  • 每个web请求有一个会话。这通常涉及在调用控制器方法之前打开会话(和事务),然后提交事务。通常,这是通过使用需要会话的方法上的属性来处理的。我不能马上给出一个完整的例子,但我知道有一种流行的方法在本文中有描述

您需要确保始终只有一个会话处于活动状态。有两种流行的方法:

  • 拥有一个始终将请求转发到的服务层。该服务层负责会话处理(和事务处理)。所有业务逻辑都必须在会话层中处理,以便始终拥有会话。您必须在UI中加载所需的所有内容,并将其作为响应的一部分返回。例如,有关使用nhibernate的简单请求-响应服务层,请参阅
  • 每个web请求有一个会话。这通常涉及在调用控制器方法之前打开会话(和事务),然后提交事务。通常,这是通过使用需要会话的方法上的属性来处理的。我不能马上给出一个完整的例子,但我知道有一种流行的方法在本文中有描述

假设您在web应用程序中使用每请求会话模式,最简单的解决方案是修改
NHibernateHelper.OpenSession
方法以返回请求的当前会话。为了实现这一点,您不能使用块将会话访问包装在
中,而是在global.asax中管理会话生存期


如果有很多不想重构的现有代码,我会采用这种方法。如果您有时间重构,那么您应该使用依赖项注入将ISession注入到存储库/查询对象中。

假设您在数据库中使用每请求会话模式
public Item FindByID(Session session, Guid itemID)
{
    using (var tr = session.BeginTransaction())
    {
        return session.Get<Item>(itemID);
    }
}

public void RemoveItem(Session session, Item item)
{
    using (var tr = session.BeginTransaction())
    {
         session.Delete(item);
         tr.Commit();
    }
}