expressappframework-403631-business-model-design-orm-resolve-session-mixing-exception.md
A View Controller contains the AddTaskAction SimpleAction that implements the following logic:
private void AddTaskAction_Execute(Object sender, SimpleActionExecuteEventArgs e){
IObjectSpace objectSpace = Application.CreateObjectSpace(typeof(Contact));
Contact contact = objectSpace.CreateObject<Contact>();
Task task = (Task)View.CurrentObject;
contact.Tasks.Add(task);
e.ShowViewParameters.CreatedView = Application.CreateDetailView(objectSpace, contact, true);
}
When XAF executes the AddTaskAction action, the Session Mixing Exception is raised: _An error with number 1021 has occurred. Error message: The object that has been passed belongs to another ObjectSpace…_
The XPO Session/UnitOfWork or XAF Object Space is a separate data context. (ObjectSpace wraps the Session/UnitOfWork.) The Session Mixing Exception occurs if you try to create a link between two objects from different Sessions or Object Spaces, for example:
The code above raises the Session Mixing Exception in the AddTaskAction_Execute method on an attempt to add a new Task to the Contact.Tasks collection. The exception is thrown because the Contact object is created in a new ObjectSpace, while the Task instance belongs to the current View Object Space.
To avoid the Session Mixing Exception , manipulate all related objects within the same data context (the same Session or Object Space).
To get an object from one data context in another data context, perform the steps below:
Call the Session.GetKeyValue method to get the object ID.
Use the GetObjectByKey or FindObject method to get a single saved object from a database.
object taskKey = ((Task)View.CurrentObject).Session.GetKeyValue(View.CurrentObject);
contact.Tasks.Add(session.GetObjectByKey<Task>(taskKey));
See the following topic for more information: Query and Shape Data (XPO).
In XAF applications, you can use the IObjectSpace.GetObject method that accepts an object from another data context. The following example shows how to use the IObjectSpace.GetObject method to load an existing Task object (the current View Object Space) to a newly created Object Space.
private void AddTaskAction_Execute(Object sender, SimpleActionExecuteEventArgs e){
IObjectSpace objectSpace = Application.CreateObjectSpace(typeof(Contact));
Contact contact = objectSpace.CreateObject<Contact>();
Task task = (Task)View.CurrentObject;
contact.Tasks.Add(objectSpace.GetObject(task));
e.ShowViewParameters.CreatedView = Application.CreateDetailView(objectSpace, contact, true);
}
See the following topic for details: Create, Read, Update and Delete Data (XAF).
Newly created and unsaved objects cannot be obtained from a database. Use the following techniques to get unsaved objects:
Load related objects in the new object data context. Use the View.ObjectSpace property to get the new object data context.
Create a nested Session (Object Space) that allows you to transfer unsaved objects between a nested data context and its parent. Refer to the following articles for more information: