过去,我已经将Linq写入了SQL查询,这些查询效果不佳。使用SQL事件探查器(或类似)我可以通过在数据库中拦截我的查询来查看我的查询是如何转换为SQL的。
有没有办法使用仅针对对象运行的Linq查询?
例如,在有向图中的边列表上考虑以下Linq查询:
var outEdges = from e in Edges
where e.StartNode.Equals(currentNode) &&
!(from d in deadEdges select d.StartNode).Contains(e.EndNode)
select e;
该代码应该选择从当前节点开始的所有边,除了那些可能导致死边的边。
现在,我怀疑这段代码是低效的,但我不知道除了分析生成的MSIL之外如何证明它。我宁愿不这样做。
有没有人知道如何在没有SQL的情况下做到这一点?
修改
当我谈论低效率时,我的意思是“大O”符号或渐近符号的低效率。在上面的例子中,代码是以O(n)还是O(n log m)甚至O(n.m)执行Linq?换句话说,执行路径的复杂性是什么?
使用Linq to SQL,我可能会看到(例如)第二个where子句被转换为为每个边运行的子查询,而不是更有效的连接。在这种情况下我可能决定不使用Linq,或者至少更改Linq,因此对于大型数据集来说它更有效。
编辑2:
Found this post - 我不知道我是如何错过它的。只是在寻找错误的东西我想:)
答案 0 :(得分:1)
我不认为你需要一个探查器......
Linq to SQL(或Linq to Entities)查询被翻译成另一种语言(SQL),然后使用优化的执行计划执行,因此很难看出究竟发生了什么;对于这种情况,分析器可能会有所帮助。另一方面,Linq to Objects查询未翻译,它们按“原样”执行。使用类SQL语法的Linq to Objects查询只是一系列方法调用的语法糖。在您的情况下,查询的完整形式将是:
var outEdges = Edges.Where(e => e.StartNode.Equals(currentNode) &&
!deadEdges.Select(d => d.StartNode).Contains(e.EndNode));
所以,基本上,你迭代Edges
,对于Edges
中的每个项目,你都会迭代deadEdges
。因此,此处的复杂性为O(n.m)
,其中n
是Edges
中的项目数,m
deadEdges
中的项目数