Динамическое построение выражения для вызова метода LINQ Where - PullRequest
1 голос
/ 16 октября 2010

Я использую некоторый код из книги для реализации универсального класса репозитория для доступа к данным EF. код использует следующие два метода для получения одной сущности по ее первичному ключу int id, предполагая, что все объекты БД имеют int PK. Тем не менее, я использую импортированную БД с в основном натуральными ключами, и я хочу сохранить все отношения FK, как они есть, то есть я не хочу перепроектировать БД для использования одного столбца int PK.

Как адаптировать приведенный ниже код для работы с многостолбцовыми ключами?

protected Expression<Func<T, bool>> CreateGetExpression<T>(int id)
{
    ParameterExpression e = Expression.Parameter(typeof(T), "e");
    PropertyInfo propInfo = typeof(T).GetProperty(KeyPropertyName);
    MemberExpression m = Expression.MakeMemberAccess(e, propInfo);
    ConstantExpression c = Expression.Constant(id, typeof(int));
    BinaryExpression b = Expression.Equal(m, c);
    Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(b, e);
    return lambda;
}

public override T Get<T>(int id)
{
    return List<T>().FirstOrDefault(CreateGetExpression<T>(id));           
}

Я хочу, чтобы мой Get метод выглядел так:

public override T Get<T>(params object[] keyValues)
{
    return List<T>().FirstOrDefault(CreateGetExpression<T>(keyValues));           
}

1 Ответ

1 голос
/ 16 октября 2010

Ну, вам нужно построить дерево выражений с несколькими проверками на равенство.Вы можете взять код, который у вас есть, для создания одной проверки на равенство и создать несколько, по одному для каждого ключа.Затем вам нужно объединить их, используя Expression.AndAlso несколько раз - поэтому, если у вас есть индивидуальные проверки на равенство e1, e2 и e3, вы можете использовать:

var e = Expression.AndAlso(Expression.AndAlso(e1, e2), e3);

Одна вещь, которую нужно отметить: вам нужно будет использовать single ParameterExpression для всего конечного выражения - так что вам нужно будет адаптировать свой метод "build одиночной проверки", чтобы принимать ParameterExpression в качестве параметра ..и вам не нужно использовать Expression.Lambda до самого конца.Таким образом, общие шаги будут выглядеть примерно так:

  • Создайте ParameterExpression
  • Для каждого ключа создайте BinaryExpression, используя Expression.Equals, используя тот же ParameterExpression, который вытолько что создали.
  • Объедините выражения равенства с несколькими вызовами, чтобы Expression.AndAlso
  • Позвоните Expression.Lambda в самом конце, чтобы создать Expression<Func<T, bool>>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...