无法访问已处置的对象。与XPO

Cannot access a disposed object. with XPO


我正在尝试保留一个 XPObject。这是我的代码:

Administrateur adm = (Administrateur)GetUserByLogin("admin");
Client clt = (Client)GetUserByLogin("client");
using(var uow = new UnitOfWork())
                {
                    Calendrier cal = new Calendrier(uow)
                    {
                        //Some string and int attributes
                        Administrateur = adm,
                        Client = clt
                    };
                    uow.CommitChanges();
                }

GetUserByLogin是returns一个Utilisateur对象的方法,其中Administrateur和Client继承自Utilisateur.

我测试了 GetUserByLogin,它工作正常。当我 运行 上面的代码是我得到的:
S

ystem.ObjectDisposedException: Cannot access a disposed object.
Object name: 'ASTDataLayer.POCO.Administrateur(1004)'.
   at DevExpress.Xpo.PersistentBase.get_Session()
   at DevExpress.Xpo.Session.ThrowIfObjectFromDifferentSession(Object obj)
   at DevExpress.Xpo.Metadata.XPMemberInfo.ProcessAssociationRefChange(Session s
ession, Object referenceMemberOwner, Object oldValue, Object newValue, Boolean s
kipNonLoadedCollections)

请帮忙,谢谢

using (UnitOfWork uow = new UnitOfWork() {
  // Do something
}

using (UnitOfWork uow = new UnitOfWork() {
  // Do something
  return persistentObjectOrCollectionOfPersistentObjects;
}

There is a big confusion about when and how to dispose of the Session or UnitOfWork. The code snippets above illustrate the correct and the incorrect approach.

If you created a UnitOfWork or Session instance just to perform some actions in the current context, you can safely dispose of the UnitOfWork or Session instance. But if you pass persistent objects to another function, you should not immediately dispose of the Session or UnitOfWork.

In the latter case, the task to dispose of the UnitOfWork/Session instance becomes tricky. You have to make sure that none of your code will use persistent objects loaded by the Session/UnitOfWork after you dispose it.


您发布的代码不包含可能导致您收到异常的错误。我想这个错误存在于 GetUserByLogin 方法中。否则,很难想象您还可以将稍后在代码中使用的 Session 实例放置在哪里。

GetUserByLogin 方法很可能是创建一个新的 Session 实例。显然,这是必要的,无法避免。但是这个方法不能处理 Session,因为它 return 结果是一个持久对象。稍后将使用此对象,并且可以出于某些目的访问 Session。在使用 GetUserByLogin 方法的代码中处理 Session 是正确的。

但是,还有一个问题。由于您的应用程序逻辑需要在同一上下文中多次调用 GetUserByLogin 方法,因此如果您尝试将 returned 对象一起使用,就会混合使用不同的会话。例如,将它们分配给第三个对象的引用属性。顺便说一下,这就是你所做的。

因此,我的建议是修改 GetUserByLogin 方法,使其接受 Session 作为参数。在这种情况下,您将始终确保您使用的是单个 Session 实例,并且可以在退出上下文之前处理它。

using(var uow = new UnitOfWork())
{
    Administrateur adm = (Administrateur)GetUserByLogin(uow, "admin");
    Client clt = (Client)GetUserByLogin(uow, "client");
    Calendrier cal = new Calendrier(uow)
    {
        //Some string and int attributes
        Administrateur = adm,
        Client = clt
    };
    uow.CommitChanges();
}