Подтвердить что ты не робот

Как я могу повторно использовать выражения в операторах LINQ?

Мне нравится повторно использовать выражения по причинам DRY, но как я могу повторно использовать выражения в инструкции LINQ?

например.

У меня

public static class MyExpressions {
    public static Expression<Func<Product,bool>> IsAGoodProduct() {
        return (p) => p.Quality>3;
    }
}

И хотел бы использовать это в операторах LINQ, поэтому

  var goodProds = from p in dataContext.Products
                  where ????? // how do I use IsAGoodProduct here?
                  select p;

Конечно, я мог бы использовать функцию IQueryableExtension.Where, но это сделало бы объединения и другие функции более уродливыми для более сложных запросов.

Возможно ли это или это ограничение LINQ?

4b9b3361

Ответ 1

Если вы перейдете из синтаксического сахара LINQ, это возможно:

var goodProds = dataContext.Products.Where(MyExpressions.IsAGoodProduct());

Без него это невозможно.

Ничего не мешает вам смешивать два стиля для создания одного запроса.

Пример:

  var goodProds = from p in dataContext.Products
                                       .Where(MyExpressions.IsAGoodProduct())
                  group p by p.Category into g 
                  select new {Category = g.Key, ProductCount = g.Group.Count()};

Ответ 2

У меня была та же проблема, и я хотел сохранить возможность использовать методы расширения в синтаксисе запроса (как с обычными поддерживаемыми функциями...). Решением может быть эта библиотека (спойлер: я автор).

Вы просто реализуете метод повторного использования дважды, один раз для общего использования и один раз для запросов.

public static class MyFunctions {
    [InjectLambda]
    public static bool IsAGoodProduct(Product product) {
        return product.Quality>3;
    }
    public static Expression<Func<Product,bool>> IsAGoodProduct() {
        return (p) => p.Quality>3;
    }
}

Фактический запрос может выглядеть так, как ожидалось.

var goodProds = from p in dataContext.Products.ToInjectable()
                where p.IsAGoodProduct()
                select p;

ToInjectable создает облегченный прокси, который заменяет IsAGoodProduct метода IsAGoodProduct (если помечен соответствующим образом) на желаемое лямбда-выражение. Таким образом, вы можете использовать методы расширения везде, где в запросе работают параметризованные методы.

Ответ 3

У нас была та же проблема. Он не поддерживается из коробки, и это большая проблема для приложений LOB. Я закончил писать статью кода-проекта о повторном использовании выражений LINQ, включая очень маленькую утилиту LinqExpressionPrjection, которая позволяет повторно использовать в проекциях (в том числе и анонимные).

Найти статью здесь.

Вы можете получить сборку для повторного использования проекции как пакет nuget, а источник находится на CodePlex.

С момента вашего сообщения прошло некоторое время. Надеюсь, это по-прежнему полезно для вас. Если нет, возможно, для других, читающих эту тему.

Ответ 4

Кстати, я столкнулся с этой полезной статьей, в которой объясняется, как вы можете создавать динамические запросы LINQ, которые ссылаются на функции Expression используя пользовательский метод расширения ToExpandable(). Предоставленное решение может использоваться в различных частях запроса LINQ Query, сохраняя при этом использование синтаксиса понимания вместо того, чтобы прибегать к синтаксису лямбда.