数据库
首页 > 数据库> > CodeGo.net>重用LINQ查询导致另一个LINQ查询,而无需重新查询数据库

CodeGo.net>重用LINQ查询导致另一个LINQ查询,而无需重新查询数据库

作者:互联网

我遇到一种情况,我的应用程序根据用户指定的过滤条件使用PredicateBuilder构造了一个动态LINQ查询(此外:请查看此link以获取最佳的EF PredicateBuilder实现).问题是该查询通常需要很长时间才能运行,并且我需要该查询的结果才能执行其他查询(即,将结果与其他表联接).如果正在编写T-SQL,则将第一个查询的结果放入一个临时表或一个表变量中,然后围绕它编写其他查询.我想从第一个查询中获取ID列表(例如List< Int32> query1IDs),然后执行以下操作:

var query2 = DbContext.TableName.Where(x => query1IDs.Contains(x.ID))

这将在理论上起作用;但是,query1ID中的ID数量可以成百上千(而LINQ表达式x => query1IDs.Contains(x.ID)被转换为T-SQL“ IN”语句,这很明显是有原因的) ),并且TableName中的行数为百万.对于解决这种情况的最佳方法,是否有人有任何建议?

编辑1:关于我在做什么的其他说明.

好的,我正在构建第一个查询(query1),它只包含我感兴趣的ID.基本上,我将使用query1来“过滤”其他表.注意:在LINQ语句的末尾,我没有使用ToList()-这时不执行查询,并且没有结果发送到客户端:

var query1 = DbContext.TableName1.Where(ComplexFilterLogic).Select(x => x.ID)

然后,我使用query1并用它来过滤另一个表(TableName2).现在,我将ToList()放在此语句的末尾,因为我想执行它并将结果带给客户端:

var query2 = (from a in DbContext.TableName2 join b in query1 on a.ID equals b.ID select new { b.Column1, b.column2, b.column3,...,b.columnM }).ToList();

然后,我使用query1并重新使用它来过滤另一个表(TableName3),执行它并将结果带给客户端:

var query3 = (from a in DbContext.TableName3 join b in query1 on a.ID equals b.ID select new { b.Column1, b.column2, b.column3,...,b.columnM }).ToList();

我可以继续对任意多个查询执行此操作:

var queryN = (from a in DbContext.TableNameN join b in query1 on a.ID equals b.ID select new { b.Column1, b.column2, b.column3,...,b.columnM }).ToList();

问题:query1需要花费很长时间才能执行.当我执行query2,query3 … queryN时,query1被执行(N-1)次…这不是一种非常有效的处理方式(尤其是因为query1不变).如前所述,如果我正在编写T-SQL,我会将query1的结果放入一个临时表中,然后在后续查询中使用该表.

编辑2:

我将把回答这个问题的功劳归功于Albin Sunnanbo的评论:

When I had similar problems with a heavy query that I wanted to reuse in several other queries I always went back to the solution of creating a join in each query and put more effort in optimizing the query execution (mostly by tweaking my indexes).

我认为这是使用实体框架所能做到的最好的事情.最后,如果性能真的变差,我可能会同意约翰·伍利的建议:

This may be a situation where dropping to native ADO against a stored proc returning multiple results and using an internal temp table might be your best option for this operation. Use EF for the other 90% of your app.

感谢所有对这篇文章发表评论的人…我感谢大家的投入!

解决方法:

如果TableName的大小不太大,无法加载整个表,则使用

var tableNameById = DbContext.TableName.ToDictionary(x => x.ID);

提取整个表格并自动将其放入ID为键的本地Dictionary中.

另一种方法是仅使用.ToList()“强制” LINQ评估,以获取整个表,并使用Linq2Objects在本地进行Where部分.

var query1Lookup = new Hashset<int>(query1IDs);
var query2 = DbContext.TableName.ToList().Where(x => query1IDs.Contains(x.ID));

编辑:
通常可以将一个查询中的一个ID:s列表存储在一个列表中,然后将该列表用作另一个查询中的过滤器,通常可以将其重写为联接.
当我在重查询中遇到类似的问题时,我想在其他几个查询中重用,因此我总是回到在每个查询中创建联接的解决方案,并花更多的精力来优化查询的执行(主要是通过调整索引).

标签:c-4-0,entity-framework-4,entity-framework-4-1,c,entity-framework
来源: https://codeday.me/bug/20191102/1989301.html