2012-07-11 45 views
3

我是linq中的新成员。所以有时候只是不明白linq是如何工作的。所以在VS2010 IDE中有任何工具或内建机制来详细调试linq执行。假设我有这个linq查询如何调试LINQ结果

var to_search = new[] { "Geo", "JCB" }; 

var result = from sr in list 
      let w = to_search.FirstOrDefault(ts => sr.Title.ToLower().Contains(ts.ToLower())) 
      where w != null 
      let a = new {sr=sr, word=w.ToLower()} 
      group a by a.word into g 
      orderby g.Count() descending 
      let sorted = g.OrderByDescending(a=> a.sr.Title.Select((c, i) => a.sr.Title.Substring(i)).Count(sub => sub.ToLower().StartsWith(a.word))) 
      from a in sorted 
      select a.sr; 

var completeList = result.Concat(list.Except(result)); 

如何详细调试上面的linq查询。请指导我。谢谢。

+0

为什么不把它分解成小块,并写每个单元的单元测试?然后写一个整体的单元测试? – 2012-07-11 20:31:56

+0

请看这篇文章 http://stackoverflow.com/questions/118341/how-to-debug-a-linq-statement – james31rock 2012-07-11 20:33:18

+0

调试LINQ结果的一部分困难是它将默认为IEnumerable 并被评估懒惰,所以传统的VS IDE调试工具只会帮助你。我推荐LINQPad,如果你想在LINQ中涂鸦和玩结果。 – 2012-07-11 20:37:32

回答

5

很多都可以写回应这个看似简单的问题!事实上,我已经在Simple-Talk.com上的文章LINQ Secrets Revealed: Chaining and Debugging中详细写过。下面是它的要点总结:

  • 您可以进入与调试一些LINQ查询,但在查询依赖于表达式和语句的组成(因为你只能跨上声明) 。
  • LINQ方法链由于基本规则而起作用:每个非终端方法以IEnumerable<T>作为输入并返回IEnumerable<T>作为输出。
  • 如果您愿意,只要符合该基本规则,您可以注入一个“禁止使用”声明来给您一个“垫脚石”。也就是说,意识到你总是可以将.Select(z => z)放在方法链中,而不会产生任何后果,请使用其中的变体:z => { return z; }
  • 您可以类似地注入一种诊断方法来提供输出,而不仅仅提供一个潜在的断点。 LINQPad,不仅仅是LINQ,而是一般的C#的优秀暂存器,它以其强大的Dump()方法的幌子提供了这一点。转储是一种对象可视化工具,可提供令人惊叹的复杂数据结构可视化。
  • 根据Bart De Smet在其内容丰富的文章LINQ to Objects – Debugging中的工作,您可以将Dump的简化版带回到Visual Studio中 - 我提供的代码附在顶部提到的文章中。
  • 感谢Robert Ivanc在LINQPad Visualizer上的工作,您甚至可以将LINQPad可视化工具带入Visual Studio(尽管您需要手动为单个表达式启动它;您无法将其挂接到Dump()方法)。

作为一个简单的例子,考虑这个简单的方法链:

string[] Words = new string[] 
{" KOOKABURRA", "Frogmouth", "kingfisher ", "loon", "merganser"}; 

Words 
     .Select(word => word.Trim()) 
     .Select(word => word.ToLower()) 
     .Where(word => word.StartsWith("k")) 
     .OrderBy(word => word); 

一旦你包括转储扩展方法在Visual Studio项目,您可以微创仪器像这样...

Words 
    .Select(word => word.Trim()) 
    .Dump() 
    .Select(word => word.ToLower()) 
    .Dump() 
    .Where(word => word.StartsWith("k")) 
    .Dump() 
    .OrderBy(word => word) 
    .Dump(); 

...或更多精心这样的...

Words 
    .Dump(w => "ORIGINAL: " + w, ConsoleColor.Yellow) 
    .Select(word => word.Trim()) 
    .Dump(w => "TRIMMED: " + w, ConsoleColor.Yellow) 
    .Select(word => word.ToLower()) 
    .Dump(w => "LOWERCASE: " + w, ConsoleColor.Green) 
    .Where(word => word.StartsWith("k")) 
    .Dump(w => "FILTERED to 'K': " + w, ConsoleColor.Red) 
    .OrderBy(word => word) 
    .Dump(w => "SORTED: " + w, ConsoleColor.Blue); 

...得到的输出呈现为无论是左侧或图的右侧,分别为: Diagnostic output from Dump method in Visual Studio

作为一个传情,我会说虽然这确实很有用,但您确实必须看到LINQPad可以使用相同的输出(here再次为您提供方便)所做的增强可视化。

0

我相信你应该可以像往常一样在任何其他代码中放置中断点。我不是100%确定的,因为我经常将LINQ语法写成匹配的扩展方法。

但是,这是另一种选择,您可以使用扩展方法重写查询,并在每个方法上添加断点。

如果有疑问,不过,用F11 :)

此外,LINQPad应该能够帮助一个好一点这里。

+0

LINQPad如何帮助我调试结果。如何在linqpad中设置断点。你能帮我指导吗?我可以下载免费版本的linqpad。请在这里发布图像,这可以帮助我可视化调试linq查询在所有步骤中的详细信息。假设例如什么被存储在让a或让w。什么是获得通过作为一个值为c amd我a.sr.Title.Select((c,我)。如何调试这种方式。寻求帮助。谢谢 – Thomas 2012-07-12 07:04:38