This is a migrated thread and some comments may be shown as answers.

Marking an objected deleted without actual deletion

3 Answers 78 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Christophla
Top achievements
Rank 1
Christophla asked on 15 Dec 2009, 07:24 PM
We need to be able to mark an object as deleted without actually deleting it from the database. This allows us to retain archival data along with satisfying any lookup fields that may still reference the deleted data.

myLookup.Deleted; // value equals false
_scope.Remove(myLookup);
_scope.Commit();
myLookup.Deleted; // value equals true

Is there a way to intercept the scope and cancel the deletion?

Additionally,
   What is the best way to set ModifiedBy, CreatedBy, etc fields? Tracking Events?

3 Answers, 1 is accepted

Sort by
0
Accepted
Peter
Top achievements
Rank 1
answered on 17 Dec 2009, 10:50 AM
Hi

Pretty sure you can't achieve this via IObjectContext.Remove - (unless the Telerik folk say otherwise) I'd say it's fundamental for an ORM that deleting an (in memory) object (ie scope.Remove in OpenAccess) causes the record to be deleted from the database on commit.

The way we handle this (and I've seen similar approaches elsewhere) is to make it part of the domain (business) logic.  The basic scheme is for the relevant classes to have a boolean field that says whether the instance is active or obsolete (typically call the property either IsActive or IsObsolete depending on which way round you prefer the test).  Then, you have a 'mark as obsolete' operation rather than a delete, plus the relevant parts of the application have to know what to do, eg filter out the obsolete instances when presenting a lookup list to the user; perhaps cross-check that an update to a entity that uses the lookup doesn't get changed to use an obsolete value.    (Gets more complicated if the business logic has more complex rules for what reference data can be used when/where.)

If you really want to use scope.Remove, it might be possible to do some processing just before commit to go through the dirty objects and re-instate the relevant objects and mark them as obsolete instead (but the OpenAccess object lifecycle documentation looks like this wouldn't be allowed).  You'd still have to handle obsolete objects elsewhere, so I'd prefer to stear clear of this and make the obsolescence concept explicit.

Hope this helps, Peter
0
Accepted
PetarP
Telerik team
answered on 18 Dec 2009, 05:02 PM
Hello Christophla,

What Peter said is basically true. Telerik OpenAccess ORM indeed does not support logical deletion out of the box. What you can do is have a bool field in the database that will act as a flag for each object weather it is deleted or not. The disadvantage of this approach is that in order to determine if an object is logically deleted you will still have to retrieve it from the database which would result in some unneeded round trips. If you are not working with extreme amounts of data and the additional round trips are not a problem for you then this approach is definitely the recommended one.
Another approach would be to have a table that is a copy of your original table with just a deleted suffix.  Then you will have to implement the IInstanceCallbacks interface. This will give you access to the PreRemove event. This event is fired just before the commit when an object is being removed. One of the events parameter is the objectscope for which the remove event was fired. Using that scope you can just initialize a new object associated with your mirror table and add it to the ObjectScope. This way the object will be deleted from the original table and it will be added to the one with the deleted suffix from where you will be able to access it when ever it is needed. Here is a very simple implementation of the PreRemove method:
public void PreRemove(IObjectScope objectScope)
        {
            Person_dl dlPerson = new Person_dl() { Person_id = this.PersonID, PersonName = this.Name };
            objectScope.Add(dlPerson);
        }


Best wishes,
Petar
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
0
Christophla
Top achievements
Rank 1
answered on 01 Feb 2012, 03:45 AM
Sorry that it took me a year to respond.. but, essentially:, this is exactly what we ended up implementing...

At the same time, I implemented my own set of events in the repositories for other modules to subscribe to. Of course, it would be nice if the object context had the same facility, but it's always wishful thinking when it can easily be implemented oneself. :-)

Thank You!
Tags
General Discussions
Asked by
Christophla
Top achievements
Rank 1
Answers by
Peter
Top achievements
Rank 1
PetarP
Telerik team
Christophla
Top achievements
Rank 1
Share this question
or