I want to include the isDeleted
values in the database to my index when the user is an admin. I used the global query filter to filter the data.
This is the code I have:
var param = Expression.Parameter(entity.ClrType);
var propertyMethodInfo = typeof(EF).GetMethod("Property").MakeGenericMethod(typeof(bool));
var isDeleted = Expression.Call(propertyMethodInfo, param, Expression.Constant("IsDeleted"));
BinaryExpression compareExpression = Expression.MakeBinary(ExpressionType.Equal, isDeleted, Expression.Constant(false));
var lambdaExpression = Expression.Lambda(compareExpression, param);
builder.Entity(entity.ClrType).HasQueryFilter(lambdaExpression);
The solution is to add additional criteria to your global query filter and make sure it's evaluated dynamically. The technique is basically explained in the Global Query Filters example:
Tip
Note the use of a DbContext instance level field: _tenantId used to set the current tenant. Model-level filters will use the value from the correct context instance. I.e. The instance that is executing the query.
The essential part is to use instance field/property/method of your DbContext
, otherwise the filter will not be dynamic.
Following that, add a field to your DbContext
:
bool includeDeleted = false;
and modify you code to produce p => this.includeDeleted || p.IsDeleted == false
:
// ...
var includeDeleted = Expression.Field(Expression.Constant(this), "includeDeleted");
var condition = Expression.OrElse(includeDeleted, compareExpression);
var lambdaExpression = Expression.Lambda(condition, param);
builder.Entity(entity.ClrType).HasQueryFilter(lambdaExpression);
How you populate that field is up to you. It could be via constructor parameter / injection, public property etc.