What Changed
If a non-persistent object implements IObjectSpaceLink and its IObjectSpaceLink.ObjectSpace property value doesn't match the object space that manipulates the object, the exception is thrown: 'An error with the number 1021 has occurred. Error message: The object that was edited belongs to a different ObjectSpace. This error can occur if you manipulate your objects via an ObjectSpace to which these objects do not belong.'
This may happen, for example, when the user opens a detail view for an object shown in a list view and the same object instance is used in both views.
Reasons for Change
In v.20.2, we extended object spaces to support more scenarios with combined persistent and non-persistent objects. The new functionality demands a more strict checking of the object's object space. Persistent objects always belong to the object space that created them and cannot be transferred to another object space. Otherwise, ORM-specific exceptions may be thrown (e.g., SessionMixingException). When non-persistent objects are combined with persistent objects, they cannot be transferred to another object space either. The same behavior is required when a non-persistent object represents a proxy of a remote object. The IObjectSpaceLink.ObjectSpace property specifies the object space to which the object is bound.
How to update your application
The IObjectSpaceLink interface is usually required when a non-persistent object contains persistent objects (reference and collection properties), and the linked object space is used to load these persistent objects. The IObjectSpaceLink interface is also required when non-persistent objects represent proxies of persistent objects stored elsewhere and should behave like persistent objects.
- If you don't need a link to the object space within your non-persistent object, do not implement the IObjectSpaceLink interface. If your non-persistent object inherits from NonPersistentBaseObject, inherit from NonPersistentLiteObject instead.
- If the IObjectSpaceLink interface is required, use separate copies of the object in different object spaces. In simple scenarios, it is enough to subscribe to the NonPersistentObjectSpace.ObjectGetting event, create a new object instance, and copy property values from the source object. For example, use the following code in the SolutionName.Module/Module file:
C#using DevExpress.ExpressApp;
private void Application_ObjectSpaceCreated(object sender, ObjectSpaceCreatedEventArgs e) {
CompositeObjectSpace compositeObjectSpace = e.ObjectSpace as CompositeObjectSpace;
if(compositeObjectSpace != null) {
if(!(compositeObjectSpace.Owner is CompositeObjectSpace)) {
compositeObjectSpace.PopulateAdditionalObjectSpaces((XafApplication)sender);
}
}
var nonPersistentObjectSpace = e.ObjectSpace as NonPersistentObjectSpace;
if(nonPersistentObjectSpace != null) {
nonPersistentObjectSpace.ObjectGetting += NonPersistentObjectSpace_ObjectGetting;
}
}
private void NonPersistentObjectSpace_ObjectGetting(object sender, ObjectGettingEventArgs e) {
NPObject obj = e.SourceObject as NPObject;
if(obj != null && ((IObjectSpaceLink)obj).ObjectSpace != sender) {
NPObject copy = new NPObject() { Name = obj.Name };
e.TargetObject = copy;
}
}
In other scenarios, you may need to maintain a dictionary of already created objects to avoid duplicates and check the dictionary in all NonPersistentObjectSpace events that return objects (ObjectGetting, ObjectByKeyGetting, ObjectsGetting, ObjectReloading). Refer to the NonPersistentObjectSpaceExtender class in the Feature Center demo for an example (FeatureCenter\FeatureCenter.Module\NonPersistentObjects\Controllers.cs).