3

我正在编写一些代码,这些代码正在使用 NHibernate 进行一些中等繁重的数据处理(是的,我知道,也许不是真正适合这项工作的工具。但这是我必须使用的)

我使用无状态会话来获取前 1000 个对象,如果需要,检查、更新并将它们添加到更新对象列表中。然后我重复接下来的 1000 个对象,直到完成。下面是代码的显着简化版本。

List<MarketOrder> updated = new List<MarketOrder>();
IStatelessSession session = SessionProvider();
int offset = 0;
bool moreToGet = true;

while (moreToGet)
{
    var result = session.Query<MarketOrder>().Where(o => o.Owner.ID == currentEntityID && !o.Updated);
    var tmp = result.Skip(offset).Take(1000);

    foreach (MarketOrder item in data) 
    { 
        notUpdated.OrderState = MarketOrderState.Closed;
        updated.Add(notUpdated);
    }

    if (data.Count == pageSize) { offset += pageSize; }
    else { moreToGet = false; }
}

然后打开另一个无状态会话以进行批量更新

IStatelessSession session = SessionProvider();
foreach (MarketOrder o in updated) { session.Update(o); }

当我运行单元测试时,出现错误:

Test 'TestProcess_AutoCloseOrder' failed: NHibernate.PropertyValueException : Error         dehydrating property value for Data.Models.MarketOrder.Owner
---- NHibernate.PropertyAccessException : Exception occurred getter of Common.Models.ModelBase.Version
-------- System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
------------ NHibernate.SessionException : proxies cannot be fetched by a stateless session

经过一番折腾,我认为错误是因为在更新中,NHibernate 试图访问正在保存的Owner属性。MarketOrder(我假设这是级联更新) Owner填充了代理,并且由于它是从无状态会话加载的,因此无法访问。

果然,如果我从常规会话而不是无状态会话加载,一切正常。这个解决方案会导致生产中的性能下降,所以我宁愿避免它。

我可以设置Owner为不延迟加载,但这不是所有类似情况的实用解决方案。

这个问题的答案:NHibernate: proxies cannot be fetched by a stateless session error message。建议获取问题属性作为初始加载的一部分,但这似乎非常浪费。我只想更新主对象的一些属性,为什么还要加载该对象的所有子引用?

我想要的是让 NHibernate 意识到只有主要MarketOrder对象发生了变化,而不必费心将更新级联到Owner. 其实现在想来,我没想到Stateless Session根本就不应该级联更新?

所以有人知道这里发生了什么以及我该如何解决它?

4

0 回答 0