Description:
I have deleted several records and want to restore them. Is it possible with XPO to "unerase" objects?
Answer:
Persistent objects, that are XPCustomObject or XPObject descendants, are not physically deleted from the database, but only marked as deleted. XPO creates a GCRecord column in the database table for a given persistent class. When an object is deleted, a not-NULL value is assigned to the GCRecord column. This is a Deferred Deletion feature. Its primary purpose is to avoid constraint violation when deleting associated objects.
You can restore a deleted object by reseting its GCRecord field to null (Nothing in VB.NET) via the SetValueMember method. Here is some sample code.
C#using DevExpress.Xpo;
using DevExpress.Data.Filtering;
using(UnitOfWork uof = new UnitOfWork()) {
ICollection col = uof.GetObjects(uof.GetClassInfo<PersistentObject1>(),
new OperandProperty("GCRecord").IsNotNull(), null, 0, true, true);
if(col == null || col.Count == 0) return;
foreach(PersistentObject1 obj in col) {
obj.SetMemberValue("GCRecord", null);
}
uof.CommitChanges();
}
Visual BasicImports DevExpress.Xpo
Imports DevExpress.Data.Filtering
Using uof As UnitOfWork = New UnitOfWork()
Dim col As ICollection = uof.GetObjects(uof.GetClassInfo(Of PersistentObject1)(), New OperandProperty("GCRecord").IsNotNull(), _
Nothing, 0, True, True)
If col Is Nothing OrElse col.Count = 0 Then
Return
End If
For Each obj As PersistentObject1 In col
obj.SetMemberValue("GCRecord", Nothing)
Next
uof.CommitChanges()
End Using
Remarks
When a child object of a one-to-many association is deleted, XPO clears its reference to a parent object. This object remains orphan when restored. This behavior is by design, because the Deferred Deletion feature is not intended for the object restoration, but for overcoming complex foreign index constraints at the database level.
You can only restore the XPCustomObject descendants. XPBaseObject and XPLiteObject descendants are deleted immediately unless you decorate them with the DeferredDeletion attribute.
See Also:
Deferred and Immediate Object Deletion
Why are objects not deleted when I delete them in the XtraGrid?
Is there a way to stop XAF from removing the references to the parent object and just fill in the GCrecord?
Our customer wants a restore functionality so we need to keep those references.
When an object with Deferred Deletion enabled is deleted, it is removed from associated collections. Associations cannot be recreated automatically when you restore a deleted object. This behavior is by design, because the Deferred Deletion feature is not intended for object restoration, but for overcoming complex foreign index constraints at the database level. I am afraid there is no suitable workaround method. Please accept our apologies for any possible inconvenience.
This saved me a lot of trouble.
Thanks
Is there some underlying reason why the references to the parent cannot be kept or deleted objects? As far as I can tell, all it would mean is that association join queries would also have to check for GCRecord being null. I'm not sure what the downside of tyhis would be, besides a small slowing down of such queries. Is there something I'm missing here? I understand this was a design decision, but am still confused as to why that cannot be revisited, as it seems keeping references around would buy restoration functionality that is desired by your users.
Hello Adrian,
I created a separate ticket on your behalf: T1011122: Why a child object clears a reference to a parent object when being deleted?. We placed it in our processing queue and will process it shortly.
Why do you use a different random value for the GCRecord-Field to mark the child-objects as deleted? If you would use the value from the master, it might be easier to detect, which deleted child-objects had belonged to the master (although the reference isn't available). The challenge would be, to have a random and unique (for the specific class of the master-object) value …
Frank Muelle i think its bad idea… Oid may by reuse…
Hello Frank,
I created a separate ticket on your behalf: T1022100: Why Deferred Deletion does not use the GCRecord field to store a parent object when deleting child objects. We placed it in our processing queue and will process it shortly.