Construir un árbol de expresiones lambda anidado para un marco de entidad ¿Relación de muchos a muchos?

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

Pregunta

Estoy tratando de construir un filtro de relaciones Entity Framework 4 Many to Many, esto es para un proyecto de datos dinámicos. Sé que necesito construir un Árbol de Expresión en el tiempo de ejecución, y estoy familiarizado con hacer esto para algo como una expresión simple como esta:

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;

}

Solo por simplicidad, estos ejemplos utilizan la base de datos de Northwind donde hay una gran cantidad de uniones de (Customers <- CustomerCustomerDemo -> CustomerDemographics). Con lo que estoy teniendo problemas es con la construcción del árbol de expresiones cuando hay un lambda anidado como en la expresión a continuación, donde estoy recuperando a todos los clientes que tienen un grupo demográfico específico de clientes.

string custDemogID = "3";

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

¿Cómo construyo el árbol de Expresión con una llamada "where", que incluye el lambda anidado para el "Cualquiera"? Cualquier ayuda es apreciada, incluso si se trata de un pseudo código sobre cómo hacerlo. No hay mucho sobre esto, estoy desesperado, por favor ayuda!

Respuesta aceptada

Aquí está la solución que he encontrado, mi mayor ayuda vino de Llamar a un método de una expresión. Lo más importante a la hora de crear un método genérico "Cualquiera". El resto fue solo encadenar las llamadas.

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;

}



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow