Override delete behaviour in NHibernate
In my application users cannot truly delete records. Rather, the record's Deleted field gets set to 1, which hides it from selects.
开发者_C百科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'm not sure.
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>
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.
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.
精彩评论