none
InvalidOperationException: When called from 'VisitLambda', rewriting node of type 'ParameterExpression' must return a non-null value of the same type RRS feed

  • Question

  • I am trying to upgrade to Entity Framework Core 3.0 from 2.2 and I am facing the below exception where I have created some expression and applied globally to all the entities as global filter. This expression condition worked fine in old version EF Core 2.2

    Codes in DbContext:

    modelBuilder.GlobalFilters<FilterColumns>(i => i.TenantId == 1, nameof(FilterColumns.TenantId));
    modelBuilder.GlobalFilters<FilterColumns>(i => i.IsActive== true, nameof(FilterColumns.IsActive));

    My Custom Class:

    public class FilterColumns
    {
       public int TenantId {get; set;}
       public bool IsActive { get; set; }
    }

    My ModelBuilder Extension Method:

    public static void GlobalFilters<TClass>(this ModelBuilder modelBuilder, Expression<Func<TClass, bool>> expression, string property)
        {
            var body = expression?.Body;
            var baseType = expression?.GetType().GetGenericArguments().FirstOrDefault()?.GetGenericArguments().FirstOrDefault();
            var propertyType = baseType?.GetProperty(property)?.PropertyType;
    
            if (body != null)
            {
                if (property != null)
                {
                    var allEntities = modelBuilder?.Model.GetEntityTypes().Where(e => e.FindProperty(property) != null).Select(e => e.ClrType).ToList();
    
                    if (allEntities != null)
                    {
                        foreach (var entity in allEntities)
                        {
                            var entityPropertyType = entity?.GetProperty(property)?.PropertyType;
    
                                if (entityPropertyType == propertyType)
                                {
                                    var param = expression?.Parameters.Single().ToString();
                                    var entityParam = Expression.Parameter(entity);
                                    var expressionVisitor = new CustomExpressionVisitor(entity, baseType, entityParam);
                                    var customExpression = expressionVisitor.Visit(expression?.Body);
    
                                    var lambdaExpression = Expression.Lambda(customExpression, entityParam);
    
                                    var oldExpression = modelBuilder?.Entity(entity).Metadata.GetQueryFilter();
    
                                    if (oldExpression != null)
                                    {
                                        lambdaExpression = Expression.Lambda(
                                                                        Expression.AndAlso(Expression.Invoke(lambdaExpression, parameter), Expression.Invoke(oldExpression, parameter)),
                                                                        oldExpression.Parameters.Single());
                                    }
    
                                    modelBuilder?.Entity(entity).HasQueryFilter(lambdaExpression);
                                }                            
                        }
                    }
                }
            }
        }


    CustomExpressionVisitor Class:

    public class CustomExpressionVisitor : ExpressionVisitor
    {
        private readonly Type entityType;
        private readonly Type baseEntityType;
        private readonly ParameterExpression param;
    
        public CustomExpressionVisitor(Type entityType, Type baseEntityType, ParameterExpression param)
        {
            this.entityType = entityType;
            this.baseEntityType = baseEntityType;
            this.param = param;
        }
        protected override Expression VisitMember(MemberExpression expression)
        {
            if (expression.Member.DeclaringType == this.baseEntityType)
            {
                return Expression.PropertyOrField(this.param, expression.Member.Name);            
            }
    
            return base.VisitMember(expression);
        }
    }


    I have expected the result from the table by applying the query filter but when I tried to access data from the table using linq query I am getting the following error. Can you anyone suggest your solution to resolve this error or any other better way to apply entity global filter in EF Core 3.0?

    Exception Details:

       at System.Linq.Expressions.ExpressionVisitor.VisitAndConvert[T](T node, String callerName)
       at System.Dynamic.Utils.ExpressionVisitorUtils.VisitParameters(ExpressionVisitor visitor, IParameterProvider nodes, String callerName)
       at System.Linq.Expressions.ExpressionVisitor.VisitLambda[T](Expression`1 node)
       at System.Linq.Expressions.Expression`1.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at Microsoft.EntityFrameworkCore.Query.ReplacingExpressionVisitor.Visit(Expression expression)
       at System.Linq.Expressions.ExpressionVisitor.VisitInvocation(InvocationExpression node)
       at System.Linq.Expressions.InvocationExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at Microsoft.EntityFrameworkCore.Query.ReplacingExpressionVisitor.Visit(Expression expression)
       at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
       at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at Microsoft.EntityFrameworkCore.Query.ReplacingExpressionVisitor.Visit(Expression expression)
       at Microsoft.EntityFrameworkCore.Query.ReplacingExpressionVisitor.Replace(Expression original, Expression replacement, Expression tree)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ExpandNavigationsInLambdaExpression(NavigationExpansionExpression source, LambdaExpression lambdaExpression)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ProcessWhere(NavigationExpansionExpression source, LambdaExpression predicate)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
       at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ApplyQueryFilter(NavigationExpansionExpression navigationExpansionExpression)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitConstant(ConstantExpression constantExpression)
       at System.Linq.Expressions.ConstantExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ExpandAndReduce(Expression query, Boolean applyInclude)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.Expand(Expression query)
       at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.Process(Expression query)
       at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
       at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
       at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
       at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.<Execute>b__0()
       at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
       at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
       at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
       at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
       at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
       at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Collections.Generic.IEnumerable<TEntity>.GetEnumerator()
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
       at SampleGlobalEntityFiltersCore3._0.Controllers.HomeController.Privacy() in D:\Git Lab Source\HelpDesk\samples\Sample_Global_Entity_Filters_Core3.0\SampleGlobalEntityFiltersCore3.0\Controllers\HomeController.cs:line 35
       at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()

    Thanks in advance.

    Tuesday, October 22, 2019 12:02 PM

All replies