156

テーブルの ID を含むリストがありUserProfileます。usingUserProfilesで取得した Id のリストに基づいてすべてを選択するにはどうすればよいですか?varLINQ

var idList = new int[1, 2, 3, 4, 5];
var userProfiles = _dataContext.UserProfile.Where(......);

ここで行き詰まりました。forループなどを使用してこれを行うことができますが、LINQ.

4

4 に答える 4

258

そのために使えますContains()IN実際に句を生成しようとすると、少し後ろ向きに感じるでしょうが、これでうまくいくはずです:

var userProfiles = _dataContext.UserProfile
                               .Where(t => idList.Contains(t.Id));

UserProfileまた、各レコードにはフィールドがあると想定していint Idます。そうでない場合は、それに応じて調整する必要があります。

于 2013-05-29T21:53:50.043 に答える
112

.Where と .Contains を使用したソリューションには、O(N 平方) の複雑さがあります。単純な .Join は、パフォーマンスが大幅に向上するはずです (ハッシュにより O(N) に近い)。したがって、正しいコードは次のとおりです。

_dataContext.UserProfile.Join(idList, up => up.ID, id => id, (up, id) => up);

そして今、私の測定結果。100,000 個の UserProfiles と 100,000 個の ID を生成しました。Join には 32 ミリ秒かかり、.Where では .Contains に 2 分 19 秒かかりました! このテストには純粋な IEnumerable を使用して、自分の主張を証明しました。IEnumerable の代わりに List を使用すると、.Where と .Contains が高速になります。とにかく違いは歴然です。最速の .Where .Contains は Set<> です。すべては、.Contains の基になるコレクションの複雑さに依存します。linq の複雑さについては、この投稿を参照してください。以下のテスト サンプルをご覧ください。

    private static void Main(string[] args)
    {
        var userProfiles = GenerateUserProfiles();
        var idList = GenerateIds();
        var stopWatch = new Stopwatch();
        stopWatch.Start();
        userProfiles.Join(idList, up => up.ID, id => id, (up, id) => up).ToArray();
        Console.WriteLine("Elapsed .Join time: {0}", stopWatch.Elapsed);
        stopWatch.Restart();
        userProfiles.Where(up => idList.Contains(up.ID)).ToArray();
        Console.WriteLine("Elapsed .Where .Contains time: {0}", stopWatch.Elapsed);
        Console.ReadLine();
    }

    private static IEnumerable<int> GenerateIds()
    {
       // var result = new List<int>();
        for (int i = 100000; i > 0; i--)
        {
            yield return i;
        }
    }

    private static IEnumerable<UserProfile> GenerateUserProfiles()
    {
        for (int i = 0; i < 100000; i++)
        {
            yield return new UserProfile {ID = i};
        }
    }

コンソール出力:

経過。参加時間: 00:00:00.0322546

Elapsed .Where .Contains time: 00:02:19.4072107

于 2014-11-03T14:26:44.100 に答える
14

それは簡単なはずです。これを試して:

var idList = new int[1, 2, 3, 4, 5];
var userProfiles = _dataContext.UserProfile.Where(e => idList.Contains(e));
于 2013-05-29T21:55:09.470 に答える