42

我有一个 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,但我可能会再次将其视为调试/斜线和刻录风格工具

4

9 回答 9

31

是的,确实可以在 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 查询中的任何位置。

于 2009-04-03T23:15:55.260 回答
29

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

于 2008-09-23T00:09:12.177 回答
18

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

在此示例中,将光标放在以下代码段中的任意位置:

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

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

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

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

于 2008-09-23T03:02:00.407 回答
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() 扩展方法的调用以允许记录。我从 Bart De Smet 的 Watch() 方法开始,在他的信息文章LINQ to Objects – Debugging 中添加了一些标签和着色以增强可视化,尽管与 LINQPad 的 Dump 输出相比它仍然相形见绌。

(2) 使用 Robert Ivanc 的LINQPad Visualizer插件将 LINQPad 的可视化直接引入 Visual Studio。不确定这是否是通过我的推动 :-),但我在撰写文章时出现的一些不便现在都在最新版本中得到了很好的解决。它具有完整的 VS2010 支持,并允许您在调试时检查您喜欢的任何对象。

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

2016.12.01 更新

而我刚刚写了上述文章的续篇,标题为简单的LINQ 调试和可视化,它揭示了真正的 LINQ 调试功能终于在 Visual Studio 2015 中出现,OzCode 中即将发布的新功能。@Dror 对这个问题的回答只是对它的一瞥,但我鼓励您阅读我的新文章以深入了解“如何做”。(而且我为 OzCode 工作。:-)

于 2010-12-10T16:24:53.003 回答
7

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

LINQ 的问题是很难调试——即使在处理简单查询时,开发人员也被迫将他/她的查询重构为一堆 foreach 循环,或者使用日志记录。即将发布的 OzCode 版本(目前作为早期访问预览版)支持 LINQ 调试,它可以帮助开发人员深入研究他们的 LINQ 代码,并查明那些难以在查询中捕获异常的地方

这就是您的查询在 OzCode 中的样子:调试 LINQ 异常

于 2016-09-13T13:11:09.447 回答
6

可以在不设置任何临时断点的情况下进入 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"
    // ...
于 2016-08-07T15:19:31.693 回答
3

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

于 2008-09-23T00:14:15.410 回答
3

从错误的外观来看,我建议您查看 line.Lines 并确保其枚举器已正确实现。我认为它不应该返回null。

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

于 2008-09-23T00:15:03.800 回答
0

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

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

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

于 2019-02-20T11:01:15.903 回答