テーブルの ID を含むリストがありUserProfile
ます。usingUserProfiles
で取得した Id のリストに基づいてすべてを選択するにはどうすればよいですか?var
LINQ
var idList = new int[1, 2, 3, 4, 5];
var userProfiles = _dataContext.UserProfile.Where(......);
ここで行き詰まりました。forループなどを使用してこれを行うことができますが、LINQ
.
そのために使えますContains()
。IN
実際に句を生成しようとすると、少し後ろ向きに感じるでしょうが、これでうまくいくはずです:
var userProfiles = _dataContext.UserProfile
.Where(t => idList.Contains(t.Id));
UserProfile
また、各レコードにはフィールドがあると想定していint
Id
ます。そうでない場合は、それに応じて調整する必要があります。
.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
それは簡単なはずです。これを試して:
var idList = new int[1, 2, 3, 4, 5];
var userProfiles = _dataContext.UserProfile.Where(e => idList.Contains(e));