In my previous post I introduced the Isg.EntityFramework.Interceptors I created. In this post, I will demonstrate the usage of another package that builds on the first: Isg.EntityFramework.Interceptors.SoftDelete
The entire SoftDelete package consists of two classes. The first is an interface:
1: public interface ISoftDelete
2: {
3: bool IsDeleted { get; set; }
4: }
The second is the SoftDeleteChangeInterceptor class.
If your domain class implements ISoftDelete, the SoftDeleteChangeInterceptor will catch the delete operation, set the IsDeleted field to true, and repurpose the operation to an Update.
Here is a unit test that demonstrates this behavior.
1: [Test]
2: public void Delete()
3: {
4: var name = Guid.NewGuid().ToString();
5:
6: using (var db = new CustomerDbContext())
7: {
8: var customer = new Customer {IsDeleted = false, Name = name};
9: db.Customers.Add(customer);
10: db.SaveChanges();
11: }
12:
13: using (var db = new CustomerDbContext())
14: {
15: var customer = db.Customers.SingleOrDefault(i => i.Name == name);
16: db.Customers.Remove(customer);
17: db.SaveChanges();
18: }
19:
20: using (var db = new CustomerDbContext())
21: {
22: var customer = db.Customers.SingleOrDefault(i => i.Name == name);
23: Assert.That(customer, Is.Not.Null);
24: Assert.That(customer.IsDeleted, Is.True);
25: }
26: }
Happy Coding!
That’s great, I have to implement Soft Deletes on a project I’m working on and this seems to be a great solution.
Does it supports “Cascade Soft Deletes”? I mean, will it also soft delete child entities?
That would be dependent on how EF handles cascade deletes. If EF adds child entities to the ChangeTracker in a deleted entity state, then yes–child entities would be soft-deleted as well. I’ve not experimented with this particular scenario though.
Another question, does it automatically filters DbSets to only show “IsDeleted!=true” entries? It would be awesome if we could create both filtered and unfiltered DbSets.
I haven’t seen any support in EF for QueryFiltering. I imagine it would require development of a custom LinqProvider, but I’m not sure. Now that EF is open source, that’s certainly something to investigate. Currently though there is no support for QueryFiltering.
Hiya. Does the interceptor handle “un-nulling” any properties pointing to parent entities? My own method removes the to be deleted entity then overrides the SaveChanges method of DbContext. Unfortunately the properties created by EF because my to be deleted entity is part of parents ICollection of remain null? So my record still exists in DB but any relation has been wiped out so unable to Un-Delete if I deleted in error?
I have the same problem with deleted entities with auditing functionality I have developed. It seems that after the status of an trny has been changed to deleted, one is unable to retrieve some of the entry’s property values, including the type of the associated POCO entity!
Perhaps someone has a way of doing that that I am not aware of?
entry.Entity.GetType() does not seem to work as it returns some sort of weird (what I assume to be) proxy type, in stead of the original POCO type?
To get the type of the entity you may be able to traverse the inheritance chain until you get to to a type in the namespace of your entity models. Alternatively you could grab the entity model types into a list and determine if entry.Entity.GetType() inherits any of them.
I haven’t specifically tested for that feature. You can create a feature request here: https://bitbucket.org/crmckenzie/isg.entityframework/issues?status=new&status=open
Even better, if you could create a small demo project with a failing unit test, it would simplify the issue for me when I look for a solution to the problem.