views:

118

answers:

2

I'm working with a database where the designers decided to mark every table with a IsHistorical bit column. There is no consideration for proper modeling and there is no way I can change the schema.

This is causing some friction when developing CRUD screens that interact with navigation properties. I cannot simply take a Product and then edit its EntityCollection I have to manually write IsHistorical checks all over the place and its driving me mad.

Additions are also horrible because so far I've written all manual checks to see if an addition is just soft deleted so instead of adding a duplicate entity I can just toggle IsHistoric.

The three options I've considered are:

  1. Modifying the t4 templates to include IsHistorical checks and synchronization.

  2. Intercept deletions and additions in the ObjectContext, toggle the IsHistorical column, and then synch the object state.

  3. Subscribe to the AssociationChanged event and toggle the IsHistorical column there.

Does anybody have any experience with this or could recommend the most painless approach?

Note: Yes, I know, this is bad modeling. I've read the same articles about soft deletes that you have. It stinks I have to deal with this requirement but I do. I just want the most painless method of dealing with soft deletes without writing the same code for every navigation property in my database.

Note #2 LukeLed's answer is technically correct although forces you into a really bad poor mans ORM, graph-less, pattern. The problem lies in the fact that now I'm required to rip out all the "deleted" objects from the graph and then call the Delete method over each one. Thats not really going to save me that much manual ceremonial coding. Instead of writing manual IsHistoric checks now I'm gathering deleted objects and looping through them.

+2  A: 

I am using generic repository in my code. You could do it like:

public class Repository<T> : IRepository<T> where T : EntityObject
{
    public void Delete(T obj)
    {
        if (obj is ISoftDelete)
            ((ISoftDelete)obj).IsHistorical = true
        else
            _ctx.DeleteObject(obj);
    }

Your List() method would filter by IsHistorical too.

LukLed
+3  A: 

As I'm sure you're aware, there is not going to be a great solution to this problem when you cannot modify the schema. Given that you don't like the Repository option (though, I wonder if you're not being just a bit hasty to dismiss it), here's the best I can come up with:

  1. Handle ObjectContext.SavingChanges
  2. When that event fires, trawl through the ObjectStateManager looking for objects in the deleted state. If they have an IsHistorical property, set that, and changed the state of the object to modified.

This could get tricky when it comes to associations/relationships, but I think it more or less does what you want.

Craig Stuntz