我有一种情况,我的应用程序根据用户指定的过滤条件使用 PredicateBuilder 构建动态 LINQ 查询(除此之外:查看此 link 以获得最佳 EF PredicateBuilder 实现)。问题是这个查询通常需要很长时间才能运行,我需要这个查询的结果来执行其他查询(即,将结果与其他表连接起来)。如果我正在编写 T-SQL,我会将第一个查询的结果放入临时表或表变量中,然后围绕它编写其他查询。我想从第一个查询中获取 ID 列表(例如 List<Int32> query1IDs
),然后执行以下操作:
这在理论上可行;然而,query1IDs
中的 ID 数量可以是数百或数千(并且 LINQ 表达式 x => query1IDs.Contains(x.ID)
被翻译成 T-SQL“IN”语句,这显然是不好的)并且 TableName 中的行数在百万。有没有人对处理这种情况的最佳方法有任何建议?
编辑 1: 关于我在做什么的额外说明。
好的,我正在构建我的第一个查询 (query1),它只包含我感兴趣的 ID。基本上,我将使用 query1 来“过滤”其他表。注意:我是 not 在LINQ语句的末尾使用了ToList()
---查询是 not 此时执行和 no 结果发送到客户端:
然后我使用 query1 并使用它来过滤另一个表 (TableName2)。我现在将 ToList()
放在此语句的末尾,因为我想执行它并将结果带给客户端:
然后我使用 query1 并重新使用它来过滤另一个表(TableName3),执行它并将结果带给客户端:
我可以继续为尽可能多的查询执行此操作:
问题:query1 需要 很长的 时间来执行。当我执行 query2, query3...queryN, query1 被执行 (N-1) 次...这不是一种非常有效的做事方式(特别是因为 query1 没有改变)。正如我之前所说,如果我在编写 T-SQL,我会将 query1 的结果放入一个临时表中,然后在后续查询中使用该表。
编辑 2:
我将回答这个问题归功于 Albin Sunnanbo 的评论:
我认为这确实是使用 Entity Framework 所能做到的最好的事情。最后,如果表现真的很糟糕,我可能会接受约翰伍利的建议:
感谢所有评论这篇文章的人......我感谢大家的投入!
最佳答案
如果 TableName 的大小不是太大而无法加载您使用的整个表
var tableNameById = DbContext.TableName.ToDictionary(x => x.ID);
获取整个表并自动将其放入以
Dictionary
为键的本地 ID
中。另一种方法是使用
.ToList()
来“强制”LINQ 评估,在这种情况下,获取整个表并使用 Linq2Objects 在本地执行 Where
部分。var query1Lookup = new Hashset<int>(query1IDs);
var query2 = DbContext.TableName.ToList().Where(x => query1IDs.Contains(x.ID));
编辑:
将来自一个查询的 ID 列表存储在一个列表中并在另一个查询中使用该列表作为过滤器通常可以重写为连接。
当我想在其他几个查询中重用一个繁重的查询时遇到类似问题时,我总是回到在每个查询中创建连接的解决方案,并在优化查询执行方面付出更多努力(主要是通过调整我的索引)。
关于c# - 在另一个 LINQ 查询中重用 LINQ 查询结果而不重新查询数据库,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7585372/