Linq: добавление условий к условию where условно
У меня есть такой запрос
(from u in DataContext.Users
where u.Division == strUserDiv
&& u.Age > 18
&& u.Height > strHeightinFeet
select new DTO_UserMaster
{
Prop1 = u.Name,
}).ToList();
Я хочу добавить различные условия, такие как возраст и рост, в зависимости от того, были ли эти условия предоставлены методу, выполняющему этот запрос. Все условия будут включать пользовательский отдел. Если указан возраст, я хочу добавить это к запросу. Точно так же, если высота была обеспечена, я хочу добавить это также.
Если бы это было сделано с использованием SQL-запросов, я бы использовал построитель строк, чтобы добавить их к основному запросу strSQL. Но здесь, в Linq, я могу думать только об использовании условия IF, где я буду писать один и тот же запрос трижды, с каждым блоком IF, имеющим дополнительное условие. Есть лучший способ сделать это?
Ответы
Ответ 1
Если вы не вызываете ToList()
и ваше окончательное сопоставление с типом DTO, вы можете добавить предложения Where
по мере продвижения и построить результаты в конце:
var query = from u in DataContext.Users
where u.Division == strUserDiv
&& u.Age > 18
&& u.Height > strHeightinFeet
select u;
if (useAge)
query = query.Where(u => u.Age > age);
if (useHeight)
query = query.Where(u => u.Height > strHeightinFeet);
// Build the results at the end
var results = query.Select(u => new DTO_UserMaster
{
Prop1 = u.Name,
}).ToList();
Это все равно приведет только к одному вызову базы данных, который будет эффективно так же эффективен, как и запись запроса за один проход.
Ответ 2
один вариант.
bool? age = null
(from u in DataContext.Users
where u.Division == strUserDiv
&& (age == null || (age != null && u.Age > age.Value))
&& u.Height > strHeightinFeet
select new DTO_UserMaster
{
Prop1 = u.Name,
}).ToList();
или вы можете переключиться на синтаксис метода для linq и использовать, если условия для присоединения выражений к предложению where.
Ответ 3
Я обычно использую цепочку методов, но имею ту же проблему. И вот расширение, которое я использую
public static IQueryable<T> ConditionalWhere<T>(
this IQueryable<T> source,
Func<bool> condition,
Expression<Func<T, bool>> predicate)
{
if (condition())
{
return source.Where(predicate);
}
return source;
}
Это помогает избежать разрывов цепи. Также полезны те же ConditionalOrderBy
и ConditionalOrderByDescending
.
Ответ 4
Вот мой код, чтобы сделать аналогичную вещь. Это метод для моего WCF SOAP Web Service api.
public FruitListResponse GetFruits(string color, bool? ripe)
{
try
{
FruitContext db = new FruitContext();
var query = db.Fruits.Select(f => f);
if (color != null)
{
query = query.Where(f => f.Color == color);
}
if (ripe != null)
{
query = query.Where(f => f.Ripe == ripe);
}
return new FruitListResponse
{
Result = query.Select(f => new Fruit { Id = f.FruitId, Name = f.Name }).ToList()
};
}
catch (Exception e)
{
return new FruitListResponse { ErrorMessage = e.Message };
}
}
Базовый запрос Select(f => f)
, что означает, в основном, ВСЕ, а предложения Where
необязательно привязаны к нему. Конечный Select
не является обязательным. Я использую для преобразования объектов строк базы данных в объекты результата "Плоды".
Ответ 5
Просто я использую его в разделе where where
public IList<ent_para> getList(ent_para para){
db.table1.Where(w=>(para.abc!=""?w.para==para.abc:true==true) && (para.xyz!=""?w.xyz==para.xyz:true==true)).ToList();
}
Ответ 6
На основе определенного условия добавьте условие
...
from u in DataContext.Users
where u.Division == strUserDiv
&& u.Age != null ? u.Age > 18 : 1== 1
&& u.Height != null ? u.Height > 18 : 1== 1
&& u.Height != null ? u.Height > 18 : 1== 1
select new DTO_UserMaster
{
Prop1 = u.Name,
}).ToList();
Ответ 7
Предполагая следующий параметр,
Int? Age = 18;
Просто используя условные операторы &&
и ||
, мы можем получить другую версию.
(from u in DataContext.Users
where u.Division == strUserDiv
&& (Age == null || u.Age > Age)
&& (Param1 == null || u.param1 == Param1)
&& u.Height > strHeightinFeet
select new DTO_UserMaster
{
Prop1 = u.Name,
}).ToList();
Как и Param1, вы можете добавить любое количество параметров для условия поиска.