使用数据时C#NHibernate与Spring LazyInitializationException

时间:2010-12-08 13:02:50

标签: c# nhibernate lazy-initialization

我正在开发一个NHibernate项目,而且我之前在加载集合时遇到问题(http://stackoverflow.com/questions/4213506/c-hibernate-criteria-loading-collection),我现在在使用数据方面遇到了问题

我正在将C#与NHibernate和Spring.Net框架结合使用,在加载例如'ordercredit'之后,我获得了一个LazyInitializationException,然后访问了ordercredit的对象。

我使用此代码获取OrderCredit:

OrderCredit oc = CreditService.getOrderCredit(ordercredit.Id);

我用于加载的代码是使用DAO实现完成的:

[Transaction(TransactionPropagation.Required, ReadOnly = true)]
public OrderCredit GetOrderCredit(long ordercreditid)
{
    var creditrules = Session.CreateCriteria(typeof(OrderCredit));
    creditrules.Add(Restrictions.Eq("Id", ordercreditid));
    return creditrules.List<OrderCredit>()[0];
}

当我在本地计算机上运行时,一切正常,我实际上打算加载那些'ordercredits'的列表,但那也出错了,所以我先尝试了一个更简单的步骤。

'OrderCredit'中的对象被定义为[OneToMany]。

当我把它放在testserver上,并尝试访问加载的OrderCredit的'OrderObject'对象时,我收到错误:

NHibernate.LazyInitializationException:正在初始化[.OrderObject#5496522] - 不能初始化代理 - 没有会话。

失败的代码:

Log.Debug(oc.OrderObject.Name);

有效的代码:

Log.Debug(oc.Id);

对于任何属于OrderCredit的对象,都会发生这种情况,但我可以访问OrderCredit的属性字段(例如OrderCredit.Id)。

此外,当我访问任何对象之前,我将数据返回到调用方法的原始函数,然后它会缓存信息,因此我可以访问它。

我已经阅读了很多关于这个问题的内容,比如关闭了Lazy,但这对我来说也不起作用(或者我在错误的地方做了那个)。

最令我失望的是,它实际上可以在我的本地计算机上运行,​​而不是在testserver上运行。我能做错什么?

非常感谢任何帮助。

第一次更新:

我现在正在使用GenericDao,使用加载1 ordercredit的默认方法。我使用以下代码通过Id加载1 ordercredit。

OrderCredit oc = GenericService.Load<OrderCredit>(Id);

GenericDAO中的代码如下,但它不会结束或中断会话,这意味着我可以访问附加到ordercredit的对象:

[Transaction(TransactionPropagation.Supports, ReadOnly = true)]
public T Load<T>(long id) where T : ISaveableObject
{
    var obj = Session.Load<T>(id);
    return obj;
}

这几乎与我在本期前面提到的函数中的代码相同。

我现在真的很困惑,因为我不知道结束会话会是什么。我会在它工作的时候使用它,但我想稍后更改它,所以我可以使用我的函数调用整个集合并通过每个循环访问它们。

目前,我使用我的'getOrderCredits'函数来获取OrderCredit对象的列表,并在foreach中获取Id,并使用GenericDao.Load获取实际项目,并可以访问对象等。当然,这不是应该的,也不是必须的。

如果我得到解决,我会感到惊讶。

1 个答案:

答案 0 :(得分:4)

这是人们在使用NHibernate时遇到的常见问题。这是因为:

  1. 您打开会话
  2. 您从引用其他实体的数据库加载实体
  3. 您关闭会话
  4. 您尝试访问引用实体的属性
  5. NHibernate尝试使用加载父实体的同一会话从数据库中懒惰地加载实体
  6. 会话已关闭,因此NHibernate会抛出像woah这样的异常。
  7. 你有几个选择:

    1. 保持会话开放时间更长,最好使用工作单元格式,这样可以更严格地控​​制。
    2. 在查询时急切地加载引用的实体:
    3. 在您的情况下,由于Spring正在为您管理您的交易,第二个选项可能是最快/最简单的解决方案。

      var creditrules = Session.CreateCriteria(typeof(OrderCredit));
      creditrules.Add(Restrictions.Eq("Id", ordercreditid))
        .SetFetchMode("OrderObject", FetchMode.Eager);
      

      这会在您加载OrderObject时加载OrderCredit