2012-06-04 3 views
60

У меня есть запрос, как этотLinq: добавление условий к пункту где условно

(from u in DataContext.Users 
     where u.Division == strUserDiv 
     && u.Age > 18 
     && u.Height > strHeightinFeet 
     select new DTO_UserMaster 
     { 
     Prop1 = u.Name, 
     }).ToList(); 

Я хочу, чтобы добавить различные условия, как возраст, рост на основе были ли предусмотрены те условия, к способу выполнения этого запроса. Все условия будут включать пользовательский раздел. Если был поставлен возраст, я хочу добавить это к запросу. Similary, если высота была предоставлена, я хочу добавить это также.

Если бы это было сделано с использованием SQL-запросов, я бы использовал построитель строк, чтобы добавить их в основной запрос strSQL. Но здесь, в Linq, я могу думать только об использовании условия IF, где я буду писать один и тот же запрос трижды, причем каждый блок IF имеет дополнительное условие. Есть лучший способ сделать это?

Спасибо за ваше время ..

+0

Красивый вопрос! с хорошо сформулированным заголовком, с более красивым ответом! – Irfan

ответ

108

Если вы не вызываете 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(); 

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

+0

Должен ли я помещать все условия где-либо в оператор "var query = .."? – user20358

+1

@ user20358 Nope - то, как написано выше, отлично работает. –

+2

Последующие Где условия агрегируются как OR или как AND? – Vi100

12

один вариант.

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.

+0

Не могу поверить, что я не думал об этом. – phil

2

Вот мой код, чтобы сделать аналогичную вещь. Это метод для моего 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 не является обязательным. Я использую для преобразования объектов строк базы данных в объекты «Фрукты».

+1

приятное объяснение – xDJR1875

7

Обычно я использую метод цепочки, но имеет ту же проблему. И вот расширение Я использую

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.

+0

Полезно, но, пожалуйста, добавьте пример того, как он будет выглядеть при использовании. – Suncat2000

+1

Это должно быть: var fruits = await db.Fruits .ConditionalWhere (() => color! = Null, f => f.Color == color) .ConditionalWhere (() => ripe! = Null, f => f.Ripe == ripe) .ToListAsync(); –

+1

Отлично работает! Благодаря! Я также сделал перегрузку для * condition * как простого логического значения вместо функции, чтобы сделать его более интуитивным, когда делегат добавит излишнюю сложность. Я использую этот метод расширения довольно часто и очень ценю ваше решение. – Suncat2000

2

Просто я использую его в своей статье, как где

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(); 
} 
0

на основе определенного Condtion добавить где условие ...

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(); 
Смежные вопросы