Entity Framework Logical Delete Part Six: Filtering deleted records the naive way

Akos Nagy
Jul 29, 2017

OK, so we've got to the point where we have a good solution for flagging deleted entities. But we still have to find a way to filter out the flagged records from query results.
Just as a reminder: we need a solution that works for entities, for related entities, has good performance, doesn't leak any abstraction and is also automated. I mean, how hard can this be? :)

The usual approaches

There are a couple of approaches that people usually try. First is the preconstructed query on the context, something like this

public class MyCtx : DbContext
  public DbSet<Person> People { get; set; }
  public IQueryable<Person> ActivePeople => People.Where( p => !p.IsDeleted);

The drawbacks are obvious: you have to include the IsDeleted property into the model. But we worked so hard to be able to leave it out! Also, why are there two "sets"? How can you guarantee that your developers would use only the .ActivePeople? Answer: no way. So the solution has good performance and allows for filtering of then entities, it leaks the abstraction, it is not automated and it doesn't allow for filtering of related entities. We need another solution.

Downloadable components

There are a couple of components floating around NuGet that people sometimes use for this kind of feature.
One of them is this one. Unfortunately, it has the uncomfortable requirement of including the IsDeleted in the model, so it falls short of the ideal right there. Also it creates quite convoluted queries, which are hard to audit and even though I haven't done any measurements, I'd think it hurts the performance.
The other one is this. Again, you have to include IsDeleted in the model. And also, it doesn't support implicitly loading filtered related entities. These are two drawbacks why I don't really like them.

It is also worth noting that EF Core 2.0 has a feature called vertical filters, which does just this. I haven't checked it out yet. But here's a good blog post on how you can use this to filter out the deleted records. (Also see how he tries to avoid to map the deleted flag into the entity classes?).

So how can you filter the deleted entities? We'll discuss that in the next post. Stay tuned!

Akos Nagy
Software engineer, software architect, software craftsman. .NET-enthusiast, Azure-fan, Javascript-hater. Amateur athlete.