Есть ли способ создать запрос LINQ как переменную, не имея источника данных (пока)?

Преамбула:
Мой основной вопрос очень похож на этот: Как я могу написать чистый репозиторий, не подвергая IQueryable остальной части моего приложения? который остался без ответа. Я надеюсь, что если я подойду к проблеме иначе и задам несколько иной вопрос, я могу получить результат. Я повторю часть содержания этого другого вопроса, чтобы читатели не читали его в контексте.

Проблема:
Я работаю с сущностями POCO и Entity Framework 4. Я пытаюсь разрешить сложную специальную фильтрацию наборов сущностей на уровне приложения, одновременно пытаясь избежать раскрытия IQueryable за пределами моего репозитория. Это оставляет меня с некоторыми осложнениями.

  • Я не хочу создавать один метод массивной фильтрации в репозитории, который принимает огромный список параметров, например:

     IEnumerable GetFilteredCustomers (string nameFilter, string addressFilter, bool isActive, int customerId, ...)
    

    Это не только чрезвычайно громоздко в использовании, но и ужасно некрасиво на вид, особенно если это в основном куча нулей и т. Д. Это также не так удобно в обслуживании, как хотелось бы.

  • Я не хочу создавать в репозитории огромный набор методов фильтрации, таких как:

     IEnumerable GetActiveCustomers ()
    IEnumerable GetCustomersByName ()
    

    У этого подхода есть ряд проблем, в том числе необходимость в огромном списке методов, который вырастает до n! где n - количество доступных условий фильтрации, если я хочу иметь возможность комбинировать их произвольным образом. (т.е. все активные клиенты с именем Джордж). Также очень сложно обслуживать.

  • Я не хочу создавать объединяемые в цепочки методы (Fluent Interface), которые манипулируют IEnumerable , потому что в конечном итоге это включает возврат огромного набора результатов из базы данных и его фильтрацию в памяти, что является не масштабируемое решение.

  • Я не могу создать Fluent Interface, который манипулирует IQueryable , потому что, как я уже сказал, я не хочу раскрывать прошлое IQueryable репозитории.

  • Я бы не хотел просто перефразировать метод единственного массивного фильтра путем передачи объекта, полного параметров, вместо большого списка параметров, хотя на данный момент это может быть наименее уродливым решением.

Идеи:
В конечном счете, я думаю, что идеальным решением было бы найти способ создать полный запрос, который не знает источника, и сохранить его как параметр. Затем я мог бы передать это в репозиторий, где источник известен, и применить запрос к источнику и вернуть результаты.

Чтобы уточнить; в отличие от простого создания объекта параметров, как упомянуто выше, я хотел бы использовать необработанные запросы LINQ, но каким-то образом сохранить их в переменной и применить их к источнику данных позже. Я подозреваю, что тип возвращаемого значения должен быть известен заранее, но меня вполне устраивает определение этого типа и его наличие заранее.

Чтобы посмотреть на это с другой точки зрения, рассмотрите следующее:

IQueryable filteredCustomers = customerRepository.GetAll()
    .Where(c => c.FirstName == "Dave")
    .Where(c => c.IsActive == true)
    .Where(c => c.HasAddress == true)
    ;

Я хочу упаковать три предложения Where как объект запроса, полностью отделенный от customerRepository.GetAll (), передать его как параметр и применить это позже.

5
задан Community 23 May 2017 в 12:01
поделиться