我爲構建搜索邏輯的動態表達式樹遇到了一個小問題。爲實體自己的屬性創建一個表達式樹工作正常,但我不知道如何添加一個表達式,它將按照子實體屬性進行過濾。過濾但屬性和子實體屬性
這是我的任務實體:
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'來枚舉。如果這不起作用,那麼可以嘗試包括導航屬性路徑(不包括路徑中的最後一個屬性;即簡單類型的實際屬性)以強制連接。 –