Динамічні умови AND і OR для методу Where Linq виразах

131

Програмування Asp.net
Попередній

Наступний

Стоїть завдання зробити сторінку пошуку, на якій дуже багато фільтрів. Фільтри між собою свзязанны умовами OR або AND. Приклад інтерфейсу:

Спочатку виникла ідея скористатися Dynamic Linq library, де запити можна писати у вигляді рядків. Але я до цієї бібліотеки ставлюся негативно, так як при зміні структури бази даних (структури таблиць), складно відстежити де потрібно внести зміни.

За цим довелося користуватися лямбда-виразів.

При створенні умов відбору, мені подобається користуватися Expression. Для прикладу розглянемо фільтр по містах (будемо відбирати компанії по місту):

Code:

//фільтр по містах. За замовчуванням фільтрації не відбувається
Expression filterCityID = p => true;

//Якщо фільтр був встановлений, то міняємо умова фільтрації
if (filter.SelectListCities.Any())
{
filterCityID = p => filter.SelectListCities.Contains(p.CityID);
}
var result = datacontext.Companies.Where(filterCityID).ToList()

Тепер перейдемо до написання умови AND між фільтрами. Для цього потрібно розуміти що таке Lazy Load – пізня завантаження. Все дуже просто. Коли ми пишемо код: datacontext.Companies.Where(p=>p.CityID == 10) запит до БД буде відбуватися тільки після виклику методу ToList. Це означає, що ми можемо писати ось так:

var result = datacontext.Companies.Where(p=>p.CityID == 10);

if(filter.SelectListSeti)
{
result = result.Where(p=> filter.SelectListSeti.Contains( p.SetiID ));
}
var data = result.ToList();

У цьому коді ми до фільтру CityID == 10 додаємо ще фільтр мереж. Або іншою мовою виконуємо умова AND.

Тепер розглянемо умову OR:

var result = datacontext.Companies.Where(p=>p.CityID == 10);

if(filter.SelectListSeti)
{
result = result.Union ( datacontext.Companies.Where(p=> filter.SelectListSeti.Contains(p.SetiID)));
}
var data = result.ToList();

Запит буде дуже важкий, але іншого я поки не придумав.