【问题标题】:Check if list contains item from other list in EntityFramework检查列表是否包含 EntityFramework 中其他列表中的项目
【发布时间】:2021-11-27 16:45:45
【问题描述】:

我有一个实体 Person,它有一个与之关联的位置列表。我需要查询人员表并从位置列表(条件)中获取所有至少具有一个位置的人。以下方法有效,但效率极低:

var searchIds = new List<int>{1,2,3,4,5};
var result = persons.Where(p => p.Locations.Any(l => searchIds.Any(id => l.Id == id)));

这适用于小型列表(例如 5-10 个 searchIds 和一个有 5-10 个位置的人。问题是有些人可能有 100 个位置,而一次搜索也可以搜索 100 个位置。当我尝试执行上面的EF实际上产生了一个2000+的SQL语句并且因为嵌套太深而失败了。虽然嵌套本身已经是一个问题,即使它可以工作,我仍然不会遇到2000+的SQL语句.

注意:实际代码还包括多个级别和父子关系,但我确实设法将其简化为仅使用 id 而不是完整对象的相当扁平的结构

在 EF 中实现此目的的最佳方法是什么?

【问题讨论】:

标签: c# database linq entity-framework


【解决方案1】:

我会建议:

var searchIds = new List<int>{1,2,3,4,5};
var result = persons.Where(p => p.Locations.Any(l => searchIds.Contains(l.Id)));

Contains 将被翻译成IN 语句。

请记住,id 列表进入 sql 语句。如果您的 id 列表很大,那么您最终会遇到很大的查询。

【讨论】:

  • 对于我的搜索列表中有 2000 多个 id 的情况没有解决方案吗?例如,在 SQL 中,我可以创建一个临时表,将 ID 存储在其中,然后在 JOIN 子句中使用它。
【解决方案2】:

尝试切换到联接而不是做大量数据包括:

var searchIds = new List<int>{1,2,3,4,5};
var results = (from p in persons
               join l in Location on p.PersonId equals l.PersonId
               where searchIds.Contains(l.Id)
               select p).Distinct().ToList();

显然修复此行以匹配您的课程和/或加入属性。

join l in Location on p.PersonId equals l.PersonId

我希望这会生成一个更友好的执行计划。

【讨论】:

  • 我和你一起讨论 ORM,所以这将是一个快速的讨论 :-) 不幸的是我不能使用连接,因为我没有位置集(使用通用存储库) .我确实发现做searchIds.Contains(l.Id)searchIds.Any(id =&gt; l.Id == id) 好很多。减少到大约 70 行 SQL,不是超级但优于 2000+
  • @Kenneth 如果您可以在 Person 类中看到 Locations 属性,我不明白为什么您无法直接查询该类。也许我没有正确理解这种情况。无论如何,我祝你好运。
  • 好吧,我只能直接访问一个 EntitySet (Persons)。其余的应该通过该类间接查询。据说 EF 处理连接并找出最佳执行路径。据说......无论如何,包含似乎是最重要的部分。感谢您的帮助
  • ??在有用的时候使用 ORM 真的很好。如果您开始遇到麻烦,请转向更好的方法。
  • 我使用的是通用存储库模式,但我不确定您为什么不能在您的实现中执行 .Join()。诚然,现在是 5 年后..
【解决方案3】:

你可以试试这个。

List<EnquirePriceSub> e = getSomethings();
var data = appDb.EnquirePriceSubs.Where(w=> e.Select(s=>s.Id).Contains(w.Id)).ToList();

【讨论】:

    猜你喜欢
    • 2018-01-03
    • 2023-03-26
    • 1970-01-01
    • 2020-08-18
    • 1970-01-01
    • 2020-04-02
    • 2012-08-26
    • 1970-01-01
    • 2014-03-02
    相关资源
    最近更新 更多