views:

181

answers:

3

Hi all

In my application users cannot truly delete records. Rather, the record's Deleted field gets set to 1, which hides it from selects.

I need to maintain this behaviour and I'm looking into whether NHibernate is appropriate for my app. Can I override NHibnernate's delete behaviour so that instead of issuing DELETE statements, it issues UPDATES, as described above?

I would obviously also need to override its SELECT behaviour to include the 'AND Deleted = 0' clause. Or read from a view instead. I dunno.

TIA for your advice.

David

+4  A: 

To implement a soft delete just bypass the Hibernate delete mechanism. Instead, map your table's Deleted field to a .Net boolean property by the same name. To delete an item, set item.Deleted = true. Then add a where attribute to your class mapping to filter out the deleted items. If you like, create another mapping for deleted items. Otherwise they will become invisible to your application, but maybe that's what you want.

Edit: Here is perhaps a better approach: use the <sql-delete> tag to write a custom delete operation for your mapping. See http://docs.jboss.org/hibernate/core/3.3/reference/en/html/querysql.html#querysql-cud. I think this in combo with the where attribute would be just the ticket. For example:

<class name="MyClass" table="my_table" where="deleted=0">
  ...
  <sql-delete>UPDATE my_table SET deleted=1 WHERE id=?</sql-delete>
</class>
nw
+1 For the Where attribute within the class mapping element. Didn't think of it myself. Thanks! =)
Will Marcouiller
Thanks! I didn't know that you could add a where attribute to a class mapping. I'll look at that!
David
+1  A: 

I think the best way to get such behaviour would be by implementing the IInterceptor interface which would allow you to perform your own code as shown within the NHibernate Documentation.

Otherwise, you could simply create a trigger on delete that would perform an update. This solution is simpler, but is this suitable for your needs?

As for the SELECT, you only need to write method that will use Criterion with a Where clause to specify the Deleted=0 thing.

Will Marcouiller
I was thinking more of using interception rather than avoiding using the Delete functionality as per the previous answer. Ultimately it depends on how easy/difficult it is to implemnent each approach I guess.Thanks to everyone!
David
There's also such a thing as a DeleteEventListener which you can use to override normal delete behaviour.http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/04/08/soft-deletes.aspx
David
That is something particularly interesting! Thanks for the hint! =)
Will Marcouiller
+3  A: 

I implemented this using INSTEAD OF DELETE triggers on SQL Server to set a delete flag bit when a SQL DELETE is issued. This has two benefits: 1) I can just issue deletes from my app. without worry and 2) It enforces soft deletes for all database access (i.e. the trigger must be temporarily disabled to hard delete). I then set up views that select the active records only and mapped NHibernate to those. This solution has worked very well for me.

Jamie Ide