2012-10-27 26 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; 

}