【问题标题】:Using Contains() in a Where LINQ query在 Where LINQ 查询中使用 Contains()
【发布时间】:2013-01-22 05:51:19
【问题描述】:

我正在使用这段代码从表中获取所需的行列表:

_userObjectSet = EntityFrameWorkContext.CreateObjectSet<User>();
List<int> selectedUserIDs = Method(); //Returns a specific set of int user IDs...
var results = _userObjectSet.Where(c => selectedUserIDs.Contains(c.ID)).ToList();

这确实有效,因为“结果”将仅包含 ID 字段与 selectedUserIDs 列表中的元素匹配的记录。

问题是,如果我查看 Windows 任务管理器,LINQ 似乎会加载表的所有行,然后将它们过滤掉。这个表中有大量的行,很快进程的权重就超过了 1GB,我不太喜欢。

我也可以看出它正在这样做是因为它需要时间来完成。

有什么方法可以告诉 LINQ 生成如下所示的查询:

SELECT * FROM Users WHERE ID IN (34,55,66,77, etc.)

这只会返回我正在寻找的确切行并使用更少的内存?

谢谢!

【问题讨论】:

  • 如果这是 linq-to-sql 应该发生的事情。您是否尝试通过将数据上下文的 Log 属性设置为调试窗口来记录生成的 SQL? selectedUserIDs 包含多少个 id?
  • 这只是一个想法(因为这是 NHibernate 所期望的),但是您是否尝试过 _userObjecSet.Where(c =&gt; selectedUserIDs.Any(y =&gt; y == c.ID)).ToList(); 或类似的? (注意:可能不是 100% 正确)
  • 表包含 800,000+ 行,List 仅包含 3000 左右。我肯定可以运行分析器。
  • @Francis 包含 3000 个项目的 SQL In 子句是很多......很多。当列表少于某些特定数量的项目时,查询提供程序可能只能创建In 子句。理想情况下,ID 值将位于数据库的另一个表中,而不是在代码中列出一个列表,您将执行Join。甚至可能值得将它们插入临时表,然后执行Join,即使 ID 是临时的。
  • @Francis ID List 是从另一个数据库查询生成的吗?是否可以将这些数据作为 IQueryable&lt;int&gt; 表示其他查询而不是项目列表?

标签: c# linq entity-framework list contains


【解决方案1】:

尝试加入..我想你可以找到不同之处...

List<int> selectedUserIDs = Method(); //Returns a specific set of int user IDs...
var results = (from u in _userObjectSet 
               join id in selectedUserIDs on u.Id equals id
               select u);

【讨论】:

    【解决方案2】:

    为此,您将需要 LinqKit 之类的东西。具体来说,请查看套件随附的 PredicateBuilder,因为我认为您需要它来解决您的问题。

    【讨论】:

    • 不确定这是否可行,考虑到List 的大小(3000 项)。
    • 虽然是一个有用的链接,但我不确定这个答案有多大帮助,因为那里没有任何明显的东西可以真正解决这个问题。
    • 我开始打字的时候没有注意到关于 3000 项的评论(这在平板电脑上有点慢)..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-14
    • 1970-01-01
    • 1970-01-01
    • 2015-04-07
    • 2016-05-18
    • 2021-03-19
    相关资源
    最近更新 更多