我有一个包含 "UserProfile "表的Id's的列表。我如何使用 "LINQ "根据我在 "var "中得到的Id列表选择所有 "UserProfiles"?
var idList = new int[1, 2, 3, 4, 5];
var userProfiles = _dataContext.UserProfile.Where(......);
我卡在这里了。我可以用for循环来做这件事,等等。但我更愿意用LINQ
来做这件事。
使用.Where和.Contains的解决方案的复杂度为O(N square)。简单的.Join应该有更好的性能(由于散列,接近于O(N))。所以正确的代码是:
_dataContext.UserProfile.Join(idList, up => up.ID, id => id, (up, id) => up);
现在是我测量的结果。我生成了100000个UserProfiles和100000个id。Join花了32ms,.Where和.Contains花了2分19秒!我使用了纯IEnumerable来测试!我使用纯IEnumerable进行测试以证明我的说法。如果你使用List而不是IEnumerable,.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};
}
}
控制台输出:
经过的.Join时间:00:00:00.0322546
已结束的 .Where .包含时间:00:02:19.4072107
这应该很简单。试试这个:
var idList = new int[1, 2, 3, 4, 5];
var userProfiles = _dataContext.UserProfile.Where(e => idList.Contains(e));