Как создать внутренний / подзапрос, используя лямбда-выражения - PullRequest
1 голос
/ 24 апреля 2020

Учитывая, что следующий запрос (с внутренним запросом) необходимо создать полностью динамически c.

set
  .Where(
    x => x.PersonNr == "1" && 
    x.WeightMeasurement == set.Where(y => y.PersonNr == "1").Select(z => z.WeightMeasurement).Max()
  )

В качестве первого шага я пытаюсь создать пример с использованием выражений linq. Тем не менее, я столкнулся с проблемами в следующей строке. Пожалуйста, помогите мне здесь:

Expression callSetSelect = Expression.Call(typeof(DynamicQueryableExtensions), "Select", new[] { dtoType, typeof(string) }, callSetWhere, lambdaSelect); 

Исключение:

System.InvalidOperationException: Нет универсального c метод 'Select' для типа 'System.Linq.Enumerable' совместим с предоставленными аргументами типа и аргументами. Аргументы типа не должны предоставляться, если метод не является универсальным c.

Построение запроса с использованием выражений

// x
ParameterExpression personOuterWhere = Expression.Parameter(dtoType, "x");
// x.PersonNr
MemberExpression personOuterPersonNr = Expression.Property(personOuterWhere, "PersonNr");
// x.WeightMeasurement
MemberExpression personWeightMeasurement = Expression.Property(personOuterWhere, "WeightMeasurement");
// x.PersonNr == "1"
Expression personOuterWherePersonNrEquals = Expression.Equal(personOuterPersonNr, Expression.Constant("1"));

// y
ParameterExpression personInnerWhere = Expression.Parameter(dtoType, "y");
// y.PersonNr
MemberExpression personInnerWherePersonNr = Expression.Property(personInnerWhere, "PersonNr");
// y.PersonNr == "1"
Expression personInnerWherePersonNrEquals = Expression.Equal(personInnerWherePersonNr, Expression.Constant("1"));
// y => y.PersonNr == "1"
LambdaExpression lambdaWhere = Expression.Lambda(personInnerWherePersonNrEquals, personInnerWhere);
// .Where(y => y.PersonNr == "1")
Expression callSetWhere = Expression.Call(typeof(Enumerable), "Where", new[] { dtoType }, Expression.Constant(set), lambdaWhere);

// z
ParameterExpression personInnerSelect = Expression.Parameter(dtoType, "z");
// z.WeightMeasurement
MemberExpression personInnerSelectWeightMeasurement = Expression.Property(personInnerSelect, "WeightMeasurement");
// z => z.WeightMeasurement
LambdaExpression lambdaSelect = Expression.Lambda(personInnerSelectWeightMeasurement, personInnerSelect);
// .Select(z => z.WeightMeasurement)
Expression callSetSelect = Expression.Call(typeof(DynamicQueryableExtensions), "Select", new[] { dtoType, typeof(string) }, callSetWhere, lambdaSelect);
//// .Max()
Expression callSetMax = Expression.Call(typeof(Enumerable), "Max", new[] { typeof(object) }, callSetSelect);

// set.Where(y => y.PersonNr == "1").Select(z => z.WeightMeasurement).Max()
Expression innerQuery = Expression.Lambda(callSetMax);
// x.WeightMeasurement == set.Where(y => y.PersonNr == "1").Select(z => z.WeightMeasurement).Max()
Expression weightMeasurementEqualsInnerQuery = Expression.Equal(personWeightMeasurement, innerQuery);
// x.PersonNr == "1" && x.WeightMeasurement == set.Where(y => y.PersonNr == "1").Select(z => z.WeightMeasurement).Max()
Expression outerWhereExpression = Expression.And(personOuterWherePersonNrEquals, weightMeasurementEqualsInnerQuery);
// x => x.PersonNr == "1" && x.WeightMeasurement == set.Where(y => y.PersonNr == "1").Select(z => z.WeightMeasurement).Max()
LambdaExpression lambdaOuterWhere = Expression.Lambda(outerWhereExpression, personOuterWhere);

return set.Where(lambdaOuterWhere);
...