我有一个包含我UserProfile
表的Id的列表。如何根据UserProfiles
使用var
获得的ID列表选择所有LINQ
?
var idList = new int[1, 2, 3, 4, 5];
var userProfiles = _dataContext.UserProfile.Where(......);
我被困在这里。我可以使用for循环等来执行此操作。但我宁愿使用LINQ
执行此操作。
答案 0 :(得分:170)
您可以使用Contains()
。当你真的想要产生一个IN
子句时会觉得有点倒退,但是应该这样做:
var userProfiles = _dataContext.UserProfile
.Where(t => idList.Contains(t.Id));
我还假设每个UserProfile
记录都会有一个int
Id
字段。如果情况并非如此,则必须进行相应的调整。
答案 1 :(得分:74)
.Where和.Contains的解决方案具有O(N平方)的复杂度。简单.Join应该有更好的性能(由于散列接近O(N))。所以正确的代码是:
_dataContext.UserProfile.Join(idList, up => up.ID, id => id, (up, id) => up);
现在我的测量结果。我生成了10万个UserProfiles和10万个ID。加入花了32毫秒和。在哪里.Contains用了2分19秒!我使用纯IEnumerable进行此测试来证明我的陈述。如果你使用List而不是IEnumerable,。Where和.Contains会更快。无论如何,差异是显着的。最快.Where .Contains与Set<&gt ;.所有这一切都取决于.Contains的基础coletions的复杂性。查看this post以了解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。包含时间:00:02:19.4072107
答案 2 :(得分:15)
很好的答案abowe,但不要忘记一个重要的事情 - 它们会提供不同的结果!
var idList = new int[1, 2, 2, 2, 2]; // same user is selected 4 times
var userProfiles = _dataContext.UserProfile.Where(e => idList.Contains(e)).ToList();
这将从DB返回2行(如果你只想要一个截然不同的用户列表,这可能是正确的)
但在很多情况下,您可能需要 未排序 结果列表。你总是要考虑一下SQL查询。请参阅eshop购物车的示例,以说明正在进行的操作:
var priceListIDs = new int[1, 2, 2, 2, 2]; // user has bought 4 times item ID 2
var shoppingCart = _dataContext.ShoppingCart
.Join(priceListIDs, sc => sc.PriceListID, pli => pli, (sc, pli) => sc)
.ToList();
这将返回DB的 5 结果。使用&#39;包含&#39;在这种情况下会出错。
答案 3 :(得分:13)
这应该很简单。试试这个:
var idList = new int[1, 2, 3, 4, 5];
var userProfiles = _dataContext.UserProfile.Where(e => idList.Contains(e));