2012-10-27 57 views
2

我想構建一個實體框架4多對多關係過濾器,這是一個動態數據項目。我知道,我需要建立在運行時的表達式目錄樹,我很熟悉這樣的東西像一個簡單的,言論是這樣的:構建實體框架的嵌套lambda表達式樹多對多關係?

private MethodCallExpression BuiltMethodCall(IQueryable _query, Type _ObjType, string _ColumnToSearch, string _SearchValue) 
{ 
ConstantExpression value = Expression.Constant(_SearchValue); 
ParameterExpression _parameter = Expression.Parameter(_ObjType, "value"); 
MemberExpression _property = Expression.Property(_parameter, _ColumnToSearch); 
BinaryExpression comparison = Expression.Equal(_property, value); 
LambdaExpression lambda = Expression.Lambda(comparison, _parameter); 

//Ex: Customers.Select(c => c).Where(value => (value.City == "Seattle")) 
MethodCallExpression _where = Expression.Call(typeof(Queryable), "Where", new Type[] { _query.ElementType }, new Expression[] { 
    _query.Expression, 
    Expression.Quote(lambda) 
}); 
return _where; 

} 

只是爲了簡單起見,這些例子使用Northwind數據庫,在那裏有是多對多連接(客戶< - CustomerCustomerDemo - > CustomerDemographics)。當我在下面的表達式中存在嵌套的lambda時,我正在構建表達式樹,在這裏我檢索具有特定客戶羣的所有客戶。

string custDemogID = "3"; 

//Get customers who have a particular demog 
dynamic cust = context.Customers.Where(c => c.CustomerDemographics.Any(cd => cd.CustomerTypeID == custDemogID)); 

如何構建具有「where」調用的Expression樹,其中包含「Any」的嵌套lambda?任何幫助表示讚賞,即使它是僞代碼如何做到這一點。這裏沒有太多,我絕望,請幫助!

+0

你試過從創建代碼表達式樹,並檢查它是如何表示嵌套的拉姆達? – svick

+0

我已經在調試中看到了它,並且可以看到嵌套的lambda,但我仍然試圖找出如何動態創建它。 –

回答

6

這是我提出的解決方案,我最大的幫助來自Calling a Method from an Expression 最重要的是要創建一個通用的「任何」方法。剩下的只是把電話連在一起。

private MethodCallExpression BuiltMethodCall(IQueryable _query, string CustTypeID, Type _ParentObjType, Type _ChildObjType, string strChildObj, string strChildCol) 
{ 

//This function will build a dynamic linq expression tree representing the ling calls of: 
//Customers.Where(c => c.CustomerDemographics.Any(cd => cd.CustomerTypeID = custTypeID)) 

ConstantExpression value = Expression.Constant(CustTypeID); 

//Build the outer part of the Where clause 
ParameterExpression parameterOuter = Expression.Parameter(_ParentObjType, "c"); 
MemberExpression propertyOuter = Expression.Property(parameterOuter, strChildObj); 

//Build the comparison inside of the Any clause 
ParameterExpression parameterInner = Expression.Parameter(_ChildObjType, "cd"); 
MemberExpression propertyInner = Expression.Property(parameterInner, strChildCol); 

BinaryExpression comparison = Expression.Equal(propertyInner, value); 
LambdaExpression lambdaInner = Expression.Lambda(comparison, parameterInner); 

//Create Generic Any Method 
Func<MethodInfo, bool> methodLambda = m => m.Name == "Any" && m.GetParameters().Length == 2; 
MethodInfo method = typeof(Enumerable).GetMethods().Where(methodLambda).Single().MakeGenericMethod(_ChildObjType); 

//Create the Any Expression Tree and convert it to a Lambda 
MethodCallExpression callAny = Expression.Call(method, propertyOuter, lambdaInner); 
LambdaExpression lambdaAny = Expression.Lambda(callAny, parameterOuter); 

//Build the final Where Call 
MethodCallExpression whereCall = Expression.Call(typeof(Queryable), "Where", new Type[] { _query.ElementType }, new Expression[] { 
    _query.Expression, 
    Expression.Quote(lambdaAny) 
}); 

return whereCall; 

}