2

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

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

我使用此代码获取 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]。

当我把它放在测试服务器上,并尝试访问加载的 OrderCredit 的“OrderObject”对象时,我得到了错误:

NHibernate.LazyInitializationException: Initializing[.OrderObject#5496522] - 无法初始化代理 - 没有会话。

失败的代码:

Log.Debug(oc.OrderObject.Name);

有效的代码:

Log.Debug(oc.Id);

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

此外,当我在将数据返回给调用该方法的原始函数之前访问任何对象时,它确实会缓存信息左右,因为那时我可以访问它。

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

最让我沮丧的是,它实际上在我的本地机器上运行,而不是在测试服务器上运行。我可能做错了什么?

非常感谢任何帮助。

第一次更新:

我现在使用的是 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;
}

这与我在此问题前面包含的函数中的代码几乎相同。

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

目前,我使用我的“getOrderCredits”函数来获取 OrderCredit 对象的列表,在 foreach 中,我获取 Id,并使用 GenericDao.Load 获取实际项目,并且可以访问对象等。当然,这不是它应该和需要的方式。

如果我能解决这个问题,我会感到惊讶。

4

1 回答 1

4

这是人们在使用 NHibernate 时经常遇到的问题。它发生是因为:

  1. 你打开一个会话
  2. 您从引用另一个实体的数据库中加载一个实体
  3. 你关闭会话
  4. 您尝试访问引用实体上的属性
  5. NHibernate 尝试使用加载父实体的同一会话从数据库中延迟加载实体
  6. 会话已关闭,因此 NHibernate 会抛出类似 woah 的异常。

你有几个选择:

  1. 让你的会话保持更长时间,最好使用类似工作单元模式的东西,这样可以让你更严格地控​​制。
  2. 查询时急切地加载引用的实体:

在您的情况下,春天正在为您管理您的交易,第二个选项可能是最快/最简单的解决方案。

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

这将OrderObject在您加载OrderCredit.

于 2011-03-02T21:10:38.153 回答