![](/img/trans.png)
[英]Error in expression tree: System.InvalidOperationException: variable 'message' of type 'A' referenced from scope '', but it is not defined
[英]System.InvalidOperationException: Variable '' of type '' referenced from scope '', but it is not defined
我正在尝试使用在C#中使用表达式的实体框架全局过滤器。 我可以对期望的表达式进行单个或组合的表达而不会出现任何问题。
我使用以下模型构建器中的属性对所有实体应用查询过滤器
注意:我尝试应用简单的查询拟合器,例如“ i => i.IsActive == true”。 使用“ AndAlso”的单个表达式和组合表达式都面临此错误。
选中后,预期查询过滤器已应用到各个表,没有任何错误。 我将从DbContext调用我的modelbuilder扩展方法,如下所示
DbContext中的代码:
modelBuilder.GlobalFilters<FilterColumns>(i => i.TenantId == 1, nameof(FilterColumns.TenantId));
我的自定义课程:
public class FilterColumns
{
public int TenantId {get; set;}
}
我的ModelBuilder扩展方法:
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 expressionVisitor = new CustomExpressionVisitor(entity, baseType, param.ToString());
var customExpression = expressionVisitor.Visit(expression?.Body);
var lambdaExpression = Expression.Lambda(customExpression, param);
modelBuilder?.Entity(entity).HasQueryFilter(lambdaExpression);
}
}
}
}
}
}
CustomExpressionVisitor类:
public class CustomExpressionVisitor : ExpressionVisitor
{
private readonly Type entityType;
private readonly Type baseEntityType;
private readonly string param;
public CustomExpressionVisitor(Type entityType, Type baseEntityType, string param)
{
this.entityType = entityType;
this.baseEntityType = baseEntityType;
this.param = param;
}
protected override Expression VisitMember(MemberExpression expression)
{
if (expression.Member.DeclaringType == this.baseEntityType)
{
var convertedParam = Expression.Parameter(entityType, this.param);
return Expression.PropertyOrField(convertedParam, expression.Member.Name);
}
return base.VisitMember(expression);
}
}
我已经通过应用查询过滤器从表中获得了预期的结果,但是当我尝试使用linq查询访问表中的数据时,出现以下错误。 谁能建议您解决此错误的解决方案?
at System.Linq.Expressions.Compiler.VariableBinder.Reference(ParameterExpression node, VariableStorageKind storage)
at System.Linq.Expressions.Compiler.VariableBinder.VisitParameter(ParameterExpression node)
at System.Linq.Expressions.ParameterExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.Compiler.VariableBinder.Visit(Expression node)
at System.Linq.Expressions.ExpressionVisitor.VisitMember(MemberExpression node)
at System.Linq.Expressions.MemberExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.Compiler.VariableBinder.Visit(Expression node)
at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.Compiler.VariableBinder.Visit(Expression node)
at System.Linq.Expressions.ExpressionVisitor.Visit(ReadOnlyCollection`1 nodes)
at System.Linq.Expressions.Compiler.VariableBinder.VisitLambda[T](Expression`1 node)
at System.Linq.Expressions.Expression`1.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.Compiler.VariableBinder.Visit(Expression node)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.Compiler.VariableBinder.Visit(Expression node)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.Compiler.VariableBinder.Visit(Expression node)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.Compiler.VariableBinder.Visit(Expression node)
at System.Linq.Expressions.ExpressionVisitor.Visit(ReadOnlyCollection`1 nodes)
at System.Linq.Expressions.Compiler.VariableBinder.VisitLambda[T](Expression`1 node)
at System.Linq.Expressions.Expression`1.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.Compiler.VariableBinder.Visit(Expression node)
at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda)
at System.Linq.Expressions.Expression`1.Compile(Boolean preferInterpretation)
at System.Linq.Expressions.Expression`1.Compile()
at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateExecutorLambda[TResults]()
at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.CreateExecutorLambda[TResults]()
at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateQueryExecutor[TResult](QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](QueryModel queryModel)
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](Expression query, IQueryModelGenerator queryModelGenerator, IDatabase database, IDiagnosticsLogger`1 logger, Type contextType)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass13_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 Remotion.Linq.QueryableBase`1.GetEnumerator()
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Collections.Generic.IEnumerable<TEntity>.GetEnumerator()
at System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
提前致谢。
Lambda表达式参数是由实例绑定的,而不是根据代码所希望的名称。
您基本上需要首先创建一个参数表达式实例,将其传递给表达式访问者,并在内部使用它绑定映射的成员表达式,最后在创建新的lambda表达式时使用它。
因此,修改访问者类,如下所示:
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);
}
}
调用代码为:
var param = Expression.Parameter(entity, "e");
var expressionVisitor = new CustomExpressionVisitor(entity, baseType, param);
var customExpression = expressionVisitor.Visit(expression?.Body);
var lambdaExpression = Expression.Lambda(customExpression, param);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.