I'm trying to persist an XPObject. Here's my code:
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
is a method that returns an Utilisateur
object, where Administrateur
and Client inherit from Utilisateur
.
I tested GetUserByLogin
and it works fine. When I run the code above here's what I get:
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)
Please help, Thanks
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.
The code you posted does not contain error that can lead to the exception you received. I suppose that this error exists in the GetUserByLogin method. Otherwise, it is difficult to imagine where else you might dispose the Session instance that is used in your code later.
The GetUserByLogin method is most probably creates a new Session instance. Obviously, this is necessary and cannot be avoided. But this method cannot dispose of the Session, because it return a persistent object as result. This object will be used later and the Session can be accessed for certain purposes. It is correctly to dispose the Session in the code that consumes the GetUserByLogin method.
However, there is another problem. Since your application logic requires to call the GetUserByLogin method multiple times in the same context, you will be mixing different Sessions if you will try to use returned objects together. For example, assign them to reference properties of a third object. This is what you did, by the way.
So, my suggestion is to modify the GetUserByLogin method, so it accepts the Session as parameter. In this situation, you will always be sure that you are using a single Session instance, and can dispose it before exiting the context.
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();
}