LinqからSQLへの「[カラム](値のリスト)の場所」の実行方法


101

IDのリストを取得する関数があり、IDに関連付けられている説明と一致するリストを返す必要があります。例えば:

public class CodeData
{
    string CodeId {get; set;}
    string Description {get; set;}
}

public List<CodeData> GetCodeDescriptionList(List<string> codeIDs)
    //Given the list of institution codes, return a list of CodeData
    //having the given CodeIds
}

したがって、これを自分で作成する場合は、次のようにします(in句にはcodeIds引数のすべての値が含まれます)。

Select CodeId, Description FROM CodeTable WHERE CodeId IN ('1a','2b','3')

Linq to Sqlでは、 "IN"句に相当するものを見つけることができないようです。私がこれまでに見つけた最高のもの(これは機能しません)は次のとおりです。

 var foo = from codeData in channel.AsQueryable<CodeData>()
           where codeData.CodeId == "1" || codeData.CodeId == "2"
           select codeData;

問題は、linq to sqlの「OR」句のリストを動的に生成できないことです。これは、それらがコンパイル時に設定されるためです。

Linq to Sqlを使用して、列をチェックするwhere句が値の動的リストにあるwhere句をどのように実現しますか?

回答:


159

使用する

where list.Contains(item.Property)

またはあなたの場合:

var foo = from codeData in channel.AsQueryable<CodeData>()
          where codeIDs.Contains(codeData.CodeId)
          select codeData;

しかし、ドット表記でも同じことができます。

var foo = channel.AsQueryable<CodeData>()
                 .Where(codeData => codeIDs.Contains(codeData.CodeId));

CodeIdが整数の場合の使用方法
キランソルカー

2
@KiranSolkar:その後、おそらくcodeIDsだろうList<int>、とすべてが大丈夫だと思います。
Jon Skeet、2016

@JonSkeet大文字と小文字は区別されませんか?codeIDsが大文字の文字列のリストで、codeData.codeIdが小文字の文字列の場合、失敗します。
PersyJack

@PersyJack:大文字と小文字を区別しないという質問には何もありませんでした。それがそうであるかどうかについては、LINQ to SQLがデフォルトで大文字と小文字の区別を強制するのか、それともdb設定がそれを管理するのかを思い出せません。
ジョンスキート2017年

1
@PersyJack LINQ to SQLはT-SQLクエリを生成します。このクエリは、大文字と小文字を区別するためにデータベース設定を使用してSQL Serverで実行されます。ただし、注意が不十分で、クエリ結果を具体化した場合、LINQをメモリ内オブジェクトに適用する前に、大文字と小文字が区別されない結果になる可能性があります。
ザレフェス2018

26

あなたも使うことができます:

List<int> codes = new List<int>();

codes.add(1);
codes.add(2);

var foo = from codeData in channel.AsQueryable<CodeData>()
          where codes.Any(code => codeData.CodeID.Equals(code))
          select codeData;

1
私は.Contains()をサポートしていませんIQToolkitの私達の実装以来、これを使用する必要がありました
DJバンWyk

1

私はJon Skeetの回答でこの方法を使用していましたが、を使用して別の方法が発生しましたConcatConcatこの方法は、限られたテストでわずかに良い行われ、それが面倒だと私はおそらくちょうどに固執うContains、または多分私は私のためにこれを行うためのヘルパーメソッドを書きます。いずれにせよ、誰かが興味を持っているなら、ここに別のオプションがあります:

メソッド

// Given an array of id's
var ids = new Guid[] { ... };

// and a DataContext
var dc = new MyDataContext();

// start the queryable
var query = (
    from thing in dc.Things
    where thing.Id == ids[ 0 ]
    select thing 
);

// then, for each other id
for( var i = 1; i < ids.Count(); i++ ) {
    // select that thing and concat to queryable
    query.Concat(
        from thing in dc.Things
        where thing.Id == ids[ i ]
        select thing
    );
}

性能試験

これは、あまり科学的ではありませんでした。データベース構造とリストに含まれるIDの数が大きな影響を与えると思います。

私はConcat、それぞれ100回の試行を行いContains、ランダム化された主キーのリストによって指定された25行を選択することを含むテストを設定しました。私はこれを約10回実行しましたが、ほとんどの場合、Concatメソッドは5〜10%速くなりContainsます。


0
 var filterTransNos = (from so in db.SalesOrderDetails
                    where  ItemDescription.Contains(ItemDescription)
                            select new { so.TransNo }).AsEnumerable();    


listreceipt = listreceipt.Where(p => filterTransNos.Any(p2 => p2.TransNo == p.TransNo)).ToList();

-1

これがHashSetを使用して実行する方法です

        HashSet<String> hs = new HashSet<string>(new String[] { "Pluto", "Earth", "Neptune" });
        String[] arr =
        {
            "Pluto",
            "Earth",
            "Neptune",
            "Jupiter",
            "Saturn",
            "Mercury",
            "Pluto",
            "Earth",
            "Neptune",
            "Jupiter",
            "Saturn",
            "Mercury",
            // etc.
        };
        ICollection<String> coll = arr;

        String[] arrStrFiltered = coll.Where(str => hs.Contains(str)).ToArray();

HashSetは基本的にほぼO(1)なので、複雑さはO(n)のままです。


これはLINQ-to-SQLについてです。このようなLINQ-to-objectsの考慮事項は適用されません。
Gert Arnold、

ICollectionはLINQ-SQLからも取得できます。これは一般的な方法です
MG

問題は、正しいSQLに変換する式を作成する方法についてです。ローカルコレクションの検索方法とは関係ありません。あなたの答えは、この区別に気づいていない将来の読者を欺くだけです。
Gert Arnold
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.