如何调试LINQ语句

时间:2008-09-23 00:06:17

标签: linq debugging linq-to-objects

我有一个Linq to objects语句

 var confirm = from l in lines.Lines 
 where (l.LineNumber == startline.LineNumber) || (l.LineNumber == endline.LineNumber) 
 select l;

确认对象在System.Linq.Enumerable.WhereListIterator`1.MoveNext()

返回'Object Null or Not A Reference'

如果查询结果为空,则只返回一个空的枚举器。我知道声明中没有空对象。是否可以单步执行LINQ语句以查看它在哪里崩溃?

编辑当我说我知道没有空对象的事实时,事实证明我在撒谎:[,但问题仍然存在,尽管我很高兴答案是“你真的不能”

LINQPad是一个好主意,我用它来自学LINQ,但我可能会再次将它看作调试/斜杠和刻录样式工具

9 个答案:

答案 0 :(得分:30)

是的,确实可以在linq查询中途暂停执行。

使用lambda表达式将linq转换为查询样式,并插入一个Select语句,该语句在linq中要调试的点之后的某处返回。一些示例代码将使其更清晰 -

        var query = dataset.Tables[0].AsEnumerable()
            .Where (i=> i.Field<string>("Project").Contains("070932.01"))
 //         .Select(i =>
 //         {return i;}
 //           )
            .Select (i=>i.Field<string>("City"));

然后取消注释评论的行。确保{return i;}在它自己的行上并在那里插入一个调试点。您可以在长而复杂的linq查询中的任何位置放置此选择。

答案 1 :(得分:28)

我不确定是否可以从VS调试,但我发现LINQPad非常有用。它将允许您转储LINQ查询的每个部分的结果。

答案 2 :(得分:17)

您应该能够在LINQ语句的where子句中的表达式上设置断点。

在此示例中,将光标放在代码的以下部分中的任何位置:

(l.LineNumber == startline.LineNumber) || (l.LineNumber == endline.LineNumber)

然后按 F9 或使用菜单或上下文菜单添加断点。

如果设置正确,只有上面的代码应该在编辑器中使用断点格式而不是整个LINQ语句。您还可以在断点窗口中查看。

如果您已正确设置,则每次都会在实现上述部分查询的函数处停止。

答案 3 :(得分:15)

我写了一篇综合性文章,回顾了2010年在Simple-Talk.com(LINQ Secrets Revealed: Chaining and Debugging)上发布的这个问题:

我谈到LINQPad(如OwenP前面提到的)作为Visual Studio的一个很棒的工具外部。特别注意其非凡的Dump()方法。您可以在LINQ链中的一个或多个点注入它,以便以非常干净和清晰的方式查看您的数据。虽然非常有用,但LINQPad是Visual Studio的外部。因此,我还提供了几种可用于 Visual Studio中的技术,因为有时将一大块代码迁移到LINQPad是不切实际的:

(1)注入我在文章中提到的Dump()扩展方法的调用以允许记录。我在他的内容文章LINQ to Objects – Debugging中开始使用Bart De Smet的Watch()方法,并添加了一些标签和颜色以增强可视化,但与LINQPad的转储输出相比仍然相形见绌。

(2)使用Robert Ivanc的LINQPad Visualizer加载项将LINQPad的可视化直接导入Visual Studio。不确定是不是通过我的刺激:-),但是当我写文章时,这对夫妇的不便现在在最新版本中得到了令人钦佩的解决。它具有完整的VS2010支持,可让您在调试时检查您喜欢的任何对象。

(3)在LINQ链的中间嵌入nop语句,以便设置断点,如前面的Amazing Pete所述。

2016.12.01更新

我刚刚写了上面文章的续集,标题为LINQ Debugging and Visualization,它揭示了真正的LINQ调试功能终于在Visual Studio 2015中与OzCode中即将发布的新功能一起到来了。 @Dror对这个问题的回答显示了它的一个小小的一瞥,但我鼓励你阅读我的新文章以深入“如何”。 (而且我为OzCode工作。: - )

答案 4 :(得分:6)

[免责声明:我在OzCode工作]

LINQ的问题在于难以调试 - 即使在处理简单查询时,开发人员也不得不将他/她的查询重构为一堆foreach循环,或者使用日志记录。 即将发布的OzCode版本(currently available as an Early Access Preview)支持LINQ调试,它还可以帮助开发人员深入研究他们的LINQ代码,并查明难以捕获查询中的异常

这是您的查询在OzCode中的样子:Debugging LINQ exception

答案 5 :(得分:5)

可以在不设置任何临时断点的情况下进入LINQ表达式。您需要进入评估 LINQ表达式的函数,例如:

var confirm = from l in lines.Lines 
              where (l.LineNumber == startline.LineNumber)
                    || (l.LineNumber == endline.LineNumber) 
              select l;

 confirm.ToArray(); // Press F11 ("Step into") when you reach this statement

 foreach(var o in q) // Press F11 when "in" keyword is highlighted as "next statement"
    // ...

答案 6 :(得分:3)

检查异常堆栈跟踪并查看执行代码的最后一位。

答案 7 :(得分:3)

从错误的外观我建议你看一下line.Lines并确保它的枚举器正确实现。我认为它不应该返回null。

哦,只需确保line和line.Lines对象不为null或返回null。

答案 8 :(得分:0)

虽然这不是一种调试方法,但我建议使用以下方法:

using (var db = new AppContext())
        {
            db.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
            // Rest of code
        }

然后,您可以在调试时检查输出窗口,以查看LINQ查询生成的SQL。