Filter all queries (trying to achieve soft delete)
Can't test the exact API, but the general approach would be to create a constrained generic method and call it via reflection:
public static class EFFilterExtensions
{
public static void SetSoftDeleteFilter(this ModelBuilder modelBuilder, Type entityType)
{
SetSoftDeleteFilterMethod.MakeGenericMethod(entityType)
.Invoke(null, new object[] { modelBuilder });
}
static readonly MethodInfo SetSoftDeleteFilterMethod = typeof(EFFilterExtensions)
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Single(t => t.IsGenericMethod && t.Name == "SetSoftDeleteFilter");
public static void SetSoftDeleteFilter<TEntity>(this ModelBuilder modelBuilder)
where TEntity : class, ISoftDeleteModel
{
modelBuilder.Entity<TEntity>().HasQueryFilter(x => !x.IsDeleted);
}
}
Now you can use something like this inside your OnModelCreating
:
foreach (var type in modelBuilder.Model.GetEntityTypes())
{
if (typeof(ISoftDeleteModel).IsAssignableFrom(type.ClrType))
modelBuilder.SetSoftDeleteFilter(type.ClrType);
}
How to code in django soft delete or how to filter query in model?
Generally speaking, a custom manager is a good candidate for this task. The example would be:
from core.managers import ABCManager
class ABC(models.Model):
soft_delete = models.BooleanField(default=False)
# other fields
objects = ABCManager()
# active = ABCActiveManager()
store your managers in the separated file (managers.py):
from django.db.models import Manager
class ABCManager(Manager):
def get_queryset(self):
query = super().get_queryset()
query = query.filter(soft_delete=False)
return query
But this is a global solution, objects
will always return instances with soft_delete=False
. In case (most likely) when you also need to get deleted objects you could instead of overriding default (objects) manager name your own differently.
Also, you could solve the issue with the class method:
class ABC(models.Model):
soft_delete = models.BooleanField(default=False)
@classmethod
def active_records(cls):
return cls.objects.filter(soft_delete=False)
And call it on the class level like so:
ABC.active_records()
# <QuerySet [<ABC: ABC object (1)>, <ABC: ABC object (2)>]>
It's quite hard to suggest a solution because it really depends on how you're going to use it later.
Global Query Filter only for GET method
If you want to work with a DbSet
that has a query filter, but need to access objects that have been filtered, you can use the IgnoreQueryFilters
method, for example:
var deletedUsers = context.Employees
.IgnoreQueryFilters()
.Where(e => e.IsDeleted);
Related Topics
How to Add 'Comments' to a Jpeg File Using C#
Windows 10 Scrollintoview() Is Not Scrolling to the Items in the Middle of a Listview
Unity Create UI Control from Script
A Type for Date Only in C# - Why Is There No Date Type
C# Sortable Collection Which Allows Duplicate Keys
Conversion from List<T> to Array T[]
Await Operator Can Only Be Used Within an Async Method
Break Out of a While Loop That Contains a Switch Statement
What Is the Use of 'Abstract Override' in C#
Initial Capacity of Collection Types, E.G. Dictionary, List
Difference Between Delegate.Invoke and Delegate()
Store a Reference to a Value Type
How to Automatically Display All Properties of a Class and Their Values in a String