0

我们有一个 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 中预览实体的地址,则此方法将按预期进行。

编辑:更改代码示例以显示事务开始/结束

4

1 回答 1

0

在调用 UpdateAddress 方法之前正在关闭会话。当您使用 Intellisense 预览属性值时,此时它是延迟加载的。仔细跟踪您的代码以查看发生这种情况的位置。如果是多线程环境,会话可能被另一个线程关闭。这通常发生在 ASP.NET 中,当使用实现不佳的按请求会话模式时。

于 2013-11-14T16:36:19.280 回答