我们有一个 WCF 服务,它使用 nHibernate 1.2 在 Oracle 数据库上执行一些操作 我们有一个处理请求的方法,其中 Transaction 在该方法之前打开,然后在该方法之后关闭(我们称之为 HandleRequest)。
在这个 HandleRequest 方法中,我从数据库加载一个对象。然后我调用一个方法 UpdateSomeStuff(object new_stuff, object entity)。在该方法中,当我尝试访问此实体的嵌套对象(如 Person.Address.StreetName)时,我收到错误“NHibernate.LazyInitializationException:无法初始化代理 - 拥有的会话已关闭。”
但是,如果我在 Update 方法之外访问同一属性,在 HandleRequest 中,一切正常。该更新方法与 HandleRequest 属于同一类。
这是一些说明这种情况的人工代码。
public Response Request(Request request)
{
Response result = null;
SessionManagerFactory.SessionManager.HandleSessionStart();
if(!SessionManagerFactory.SessionManager.TransactionExists())
SessionManagerFactory.SessionManager.BeginTransaction();
try
{
result = HandleRequest(request);
SessionManagerFactory.SessionManager.CommitTransaction();
}
catch (Exception ex)
{
SessionManagerFactory.SessionManager.RollbackTransaction();
log.Error(ex);
}
finally
{
SessionManagerFactory.SessionManager.HandleSessionEnd();
}
return result;
}
public MessageResponse HandleRequest(Request pRequest)
{
Person person = SessionManagerFactory.SessionManager.Session.Load(typeof(Person), pRequest.PersonId);
UpdateAddress(person,pRequest.NewAddress);
person.Address.StreetName = pRequest.NewAddress.StreetName; // <-- No exception here, work fine.
}
private void UpdateAddress(Person person, Address newAddress)
{
person.Address.StreetName = newAddress.StreetName; // <-- Exception here !
}
当然,我要么执行 UpdateAddress,要么执行其他任务,而不是同时执行这两个任务。
如果我调试此方法并在 UpdateAddress(..) 方法之前中断,并在 VisualStudio 中预览实体的地址,则此方法将按预期进行。
编辑:更改代码示例以显示事务开始/结束