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-запросов, я бы использовал string builder, чтобы добавить их к основному запросу strSQL. Но здесь, в Linq, я могу думать только об использовании условия IF, где я буду писать один и тот же запрос трижды, причем каждый блок IF имеет дополнительное условие. Есть ли лучший способ сделать это?
Спасибо за ваше время..
6 ответов:
Если вы не называете
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();Это все равно приведет только к одному вызову базы данных, что будет эффективно так же эффективно, как и запись запроса за один проход.
один вариант.
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 и использовать условия if для присоединения выражений к предложению where.
Я обычно использую метод цепочки, но имеют ту же проблему. А вот расширение я использую
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полезны.
вот мой код, чтобы сделать подобную вещь. Это метод на моем 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- это необязательно. Я использую для преобразования объектов строк базы данных в результирующие "фруктовые" объекты.
просто я использую его в моем предложении 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(); }
на основе определенного условия добавить условие where ...
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();
Comments