Description
Hi,
I'm having a strange problem with new global query filters (HasQueryFilter). My code is complicated since I'm developing an application framework. So, I will share the related code.
- Using HasQueryFilter like that:
modelBuilder.Entity<TEntity>().HasQueryFilter(CreateFilterExpression<TEntity>());
- CreateFilterExpression is defined as below:
protected virtual Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>() where TEntity : class
{
Expression<Func<TEntity, bool>> expression = PredicateBuilder.True<TEntity>();
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
{
expression = expression.And(e => !IsSoftDeleteFilterEnabled || !((ISoftDelete) e).IsDeleted);
}
if (typeof(IMayHaveTenant).IsAssignableFrom(typeof(TEntity)))
{
expression = expression.And(e => !IsMayHaveTenantFilterEnabled || ((IMayHaveTenant)e).TenantId == CurrentTenantId);
}
if (typeof(IMustHaveTenant).IsAssignableFrom(typeof(TEntity)))
{
expression = expression.And(e => !IsMustHaveTenantFilterEnabled || (CurrentTenantId == null || ((IMustHaveTenant)e).TenantId == CurrentTenantId));
}
return expression;
}
What I'm achiving here to combine soft delete and multitenant filters based on implemented interfaces of entities, as can be understood easily.
I'm using this PredicateBuilder (http://www.albahari.com/nutshell/predicatebuilder.aspx) to create the expression.
IsSoftDeleteFilterEnabled
, IsMayHaveTenantFilterEnabled
, CurrentTenantId
... are properties of my dbcontext.
Problem
The problem is !IsSoftEnabled
(and other boolean flags) is not properly working. It caches the first dbcontext instance and never called again for later dbcontext instances. But CurrentTenantId
property is properly called (there is interesting thing here: It's called one more time for each different query, before the actual query - I suppose it's for caching the query, but no problem).
The interesting this is that, when I compare IsSoftEnabled
value with a property of the entity, it starts working. I suppose when we compare it via an entity property (like IsSoftDeleteFilterEnabled == e.IsDeleted || !((ISoftDelete) e).IsDeleted
- this is just a stupid example) it does not grab value, but gets the expression property.
For this reason, I can not properly create a boolean flag to disable/enable a filter individually.