我为构建搜索逻辑的动态表达式树遇到了一个小问题。为实体自己的属性创建一个表达式树工作正常,但我不知道如何添加一个表达式,它将按照子实体属性进行过滤。过滤但属性和子实体属性
这是我的任务实体:
public class Task: Entity
{
public TaskType Type { get; set; }
public TaskPriority Priority { get; set; }
public int ProjectId { get; set; }
public Project Project { get; set; }
}
这里是项目实体:
public class Project: Entity
{
public int CustomerId { get; set; }
public Customer Customer { get; set; }
}
和逻辑构建动态表达:
public Func<TaskItem, bool> Build(IList<Filter> filters)
{
ParameterExpression param = Expression.Parameter(typeof(TaskItem), "task");
List<Filter> priorityFilter = FilterFilters(filters, "Priority");
List<Filter> typeFilter = FilterFilters(filters, "Type");
List<Filter> customerFilter = FilterFilters(filters, "CustomerId");
Expression expression = null;
// BuildExpression is a method which simply creates expression which is using Tasks properties (like Type or Priority)
expression = BuildExpression(param, priorityFilter, expression);
expression = BuildExpression(param, typeFilter, expression);
// This part need's to be reworked
ParameterExpression projectParam = Expression.Parameter(typeof(Project), "project");
Expression projectCustomerExpression = Expression.Equal(Expression.PropertyOrField(projectParam, "CustomerId"), Expression.Constant(customerFilter[0].Value));
Expression customerExpression = Expression.Equal(Expression.PropertyOrField(param, "Project"), projectCustomerExpression);
Expression finall = expression != null ? Expression.AndAlso(expression, projectCustomerExpression) : projectCustomerExpression;
// End of filtering by CutomerId
return Expression.Lambda<Func<TaskItem, bool>>(finall, param).Compile();
}
我不知道怎么样通过CustomerId进行过滤。上面代码标记为This part need's to be reworked
的部分可能是错误的,或者至少是其最后部分。这个想法是扩展现有的表达式(这个由BuildExpression
方法构建的表达式)和一个将由CustomerId过滤的表达式。
我已经在这方面失去了一些时间,尝试自己寻找答案,但没有结果。
任何帮助?
谢谢 - 你救了我的一天!但是当我像这样调用ToList()时,我得到“对象引用未设置为对象的实例”:'Context.Tasks.Where(searchCondition).ToList()'(搜索条件包含表达它是'IQueryable')。堆栈跟踪:在System.Linq.Enumerable的System.Linq.Enumerable.WhereEnumerableIterator1.ToList()处的lambda_method(Closure,Task)处。ToList [TSource](IEnumerable1 source)'。 任何想法? –
@DawidRutkowski很可能'Project'是'null'。如果你想填充'IQueryable',你最好改变方法签名来返回'Expression >'并移除'Compile()'调用。目前,即使您的源代码是'IQueryable ',编译器也会调用'IEnumerable '上的Where'方法。 –
@DawidRutkowski虽然我不确定,但是可能的原因会像@IvanStoev指出的那样。如果你在'searchCondition'上使用'.Compile',那么你不必这样做,除非你想避免延迟加载。相反,您可以直接将'searchCondition'应用于'IQueryable'数据,然后'ToList'来枚举。如果这不起作用,那么可以尝试包括导航属性路径(不包括路径中的最后一个属性;即简单类型的实际属性)以强制连接。 –