使用linq根据Id's列表选择多条记录

本文关键字:选择 列表 记录 根据 linq Id 使用 | 更新日期: 2023-09-27 18:15:53

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

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

我被卡在这里了。我可以用for循环等等。但是我更愿意用LINQ

使用linq根据Id's列表选择多条记录

您可以使用Contains()。当您真正尝试生成IN子句时,它会感觉有点落后,但应该这样做:

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

我还假设每个UserProfile记录将有一个int Id字段。如果不是这样的话,你需要做相应的调整。

包含。where和。contains的解复杂度为0 (N平方)。简单的. join应该有更好的性能(由于哈希,接近0 (N))。所以正确的代码是:

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

现在是我的测量结果。我生成了100,000个UserProfiles和100,000个id。Join花了32毫秒,where with contains花了2分19秒!我使用纯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};
        }
    }
控制台输出

:

运行时间:00:00:00.0322546

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

上面的答案很好,但不要忘记一个重要的事情-它们提供不同的结果!

  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行(如果您只想要一个不同排序的用户列表,这可能是正确的)

BUT在许多情况下,您可能需要一个未排序的结果列表。您必须将其视为SQL查询。请参阅商店购物车的示例,以说明发生了什么:

  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结果。在这种情况下,使用'contains'是错误的。

这应该很简单。试试这个:

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