Build a nested lambda Expression Tree for an Entity Framework Many to Many relationship?

.net entity-framework expression-trees linq many-to-many

Question

I am trying to build an Entity Framework 4 Many to Many relationship filter, this is for a Dynamic Data project. I know that I need to build an Expression Tree at run time, and I am familiar with doing this for something like a simple where expression like this:

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;

}

Just for simplicity, these examples use the Northwind database where there is a many to many join of (Customers <- CustomerCustomerDemo -> CustomerDemographics). What I am having trouble with is building the expression tree when there is a nested lambda like in the expression below, where I am retrieving all customers who have a specific customer demographic.

string custDemogID = "3";

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

How do I build the Expression tree having a "where" call, that includes the nested lambda for the "Any"? Any help is appreciated, even if it is pseudo code on how to do it. There is not much out the on this, I am desperate, please help!

Accepted Answer

Here is the solution that I have come up with, my biggest help came from Calling a Method from an Expression The biggest thing to over come was to create a generic "Any" method. The rest was just chaining the calls together.

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;

}



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why