Skip to content

HasQueryFilter does not compile expression correctly in some cases #9502

Closed as duplicate
@hikalkan

Description

@hikalkan

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.

  1. Using HasQueryFilter like that:
modelBuilder.Entity<TEntity>().HasQueryFilter(CreateFilterExpression<TEntity>());
  1. 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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions