119

このようなクエリがあります

(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では、同じクエリを3回記述し、各IFブロックに追加の条件を設定するIF条件を使用することしか考えられません。これを行うためのより良い方法はありますか?

4

9 に答える 9

217

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回のパスでクエリを作成するのと同じくらい効率的です。

于 2012-06-04T16:31:47.203 に答える
28

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

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、役に立ちます。

于 2016-03-11T02:07:19.880 に答える
22

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句にアタッチすることもできます。

于 2012-06-04T16:28:06.983 に答える
7

単に私はそれを私の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();
}
于 2016-12-15T22:58:28.627 に答える
5

特定の条件に基づいて、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();
于 2017-10-10T14:52:08.990 に答える
3

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

于 2015-05-19T20:37:11.900 に答える
1

ここで上記の受け入れられた答えに追加するだけで、結合で動的検索を実行している場合は、最初のlinqクエリで両方のテーブル(t1、t2)を含む新しいオブジェクトを返すことを検討してください。そうすれば、それらに個別にアクセスして条件付きを実行できます。探す。

var query = from t1 in _context.Table1
            join t2 in _context.Table2 on t1.Table1Id equals t2.Table1IdId
            select new { t1, t2 };

        if (!string.IsNullOrEmpty(searchProperty1))
        {
            query = query.Where(collection => collection.t1.TableColumn == searchProperty1);
        }
        if (!string.IsNullOrEmpty(searchProperty2))
        {
            query = query.Where(collection => collection.t2.TableColumn == searchProperty2);
        }
        ....etc.

2つのテーブルを結合し、いずれかのテーブルの特定の列をクエリすることに関して、ここで探していた答えが得られました。

于 2020-02-21T11:05:12.807 に答える
0

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

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

于 2019-08-12T12:15:04.787 に答える
0

私はちょうど何か他のものを探してこれに出くわしました、しかし私がラムダバージョンを投げると思いました。

まず、次のようなクラスを作成して、パラメーターをデータレイヤーに渡します。

   public class SearchParameters() {
       public int? Age {get; set;}
       public string Division {get;set;}
       etc
    }

次に、私のデータレイヤーでは、次のようになります。

public IQueryable<User> SearchUsers(SearchParameters params) 
{
    var query = Context.Users;
    if (params.Age.HasValue)
    {
         query = query.Where(u => u.Age == params.Age.Value);
    }
    if (!string.IsNullOrEmpty(params.Division)
    {
        query = query.Where(u => u.Division == params.Division);
    }
    etc
    return query;
}

クエリを具体化する場所はあなた次第です。アプリとデータの間に、db固有の表現をdbに依存しないものに変換するレイヤーがある場合があります(複数のデータソースをクエリする場合があります)。そのレイヤーは、たとえば、これらのソースから複数のタイプのクエリ可能オブジェクトを取得し、それらを共通のPOCO表現にマップする場合があります。

于 2019-12-05T21:05:10.783 に答える