web-dev-qa-db-ja.com

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ブロックに追加の条件があり、同じクエリを3回書くIF条件の使用のみを考えることができます。これを行うためのより良い方法はありますか?

御時間ありがとうございます..

86
user20358

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

これにより、データベースへの呼び出しが1回だけになり、1回のパスでクエリを記述するのと同じくらい効率的になります。

149
Reed Copsey

1つのオプション。

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句に式を添付できます。

15
Matthew Vines

私は通常、メソッドチェーンを使用しますが、同じ問題があります。そして、ここに私が使用する拡張機能があります

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;
    }

チェーンの破損を防ぐのに役立ちます。また、同じConditionalOrderByConditionalOrderByDescendingが役立ちます。

11

単純に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();
}
3
Own

同様のことをするためのコードを次に示します。これは私の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はオプションです。データベース行オブジェクトを結果の「フルーツ」オブジェクトに変換するために使用します。

3
John Henckel

特定の条件に基づいて、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();
2
Melu

次のパラメータを仮定すると、

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と同様に、検索条件に任意の数のパラメーターを追加できます。

0
Sushant yelpale