根据带有linq的Id列表选择多个记录

时间:2013-05-29 21:51:44

标签: c# linq

我有一个包含我UserProfile表的Id的列表。如何根据UserProfiles使用var获得的ID列表选择所有LINQ

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

我被困在这里。我可以使用for循环等来执行此操作。但我宁愿使用LINQ执行此操作。

4 个答案:

答案 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));