C# 调试 LINQ 查询
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/952796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Debugging LINQ Queries
提问by GWLlosa
We've been doing a lot of work with LINQ lately, mainly in a LINQ-to-Objects sense. Unfortunately, some of our queries can be a little complicated, especially when they start to involve multiple sequences in combinations. It can be hard to tell exactly what's going on, when you get queries that start to look like:
我们最近在 LINQ 方面做了很多工作,主要是在 LINQ 到对象的意义上。不幸的是,我们的一些查询可能有点复杂,尤其是当它们开始涉及多个序列的组合时。当您收到开始看起来像这样的查询时,很难确切地知道发生了什么:
IEnumerable<LongType> myCompanies = relevantBusiness.Children_Companies
.Select(ca => ca.PR_ContractItemId)
.Distinct()
.Select(id => new ContractedItem(id))
.Select(ci => ci.PR_ContractPcrId)
.Distinct()
.Select(id => new ContractedProdCompReg(id))
.Select(cpcr => cpcr.PR_CompanyId)
.Distinct();
var currentNewItems = myCompanies
.Where(currentCompanyId => !currentLic.Children_Appointments.Select(app => app.PR_CompanyId).Any(item => item == currentCompanyId))
.Select(currentId => new AppointmentStub(currentLic, currentId))
.Where(currentStub=>!existingItems.Any(existing=>existing.IsMatch(currentStub)));
Items = existingItems.Union(newItems).ToList();
etc., etc...
等等等等...
Even when you debug, it can be difficult to tell who's doing what to who and when. Short of gratuitously calling "ToList" on sequences to get things I can examine more easily, does anyone have any good suggestions for how to debug "complicated" LINQ?
即使在您进行调试时,也很难分辨谁在何时对谁做什么。除了在序列上无缘无故地调用“ToList”以获得我可以更轻松地检查的东西之外,有人对如何调试“复杂的”LINQ有什么好的建议吗?
采纳答案by mqp
A query like that seems to indicate to me that you're not doing a good job choosing appropriate data structures, or doing a good job with encapsulation and separation of tasks. I'd suggest taking a look at it and breaking it up.
像这样的查询在我看来似乎表明您在选择合适的数据结构方面做得不好,或者在封装和任务分离方面做得不好。我建议看看它并打破它。
In general, though, if I want to debug a LINQ query that isn't obviously correct, I'd break it up into subqueries and examine the results one-at-a-time in the debugger.
但是,一般来说,如果我想调试一个明显不正确的 LINQ 查询,我会将其分解为子查询并在调试器中一次检查一个结果。
回答by Daniel Brückner
回答by Cristian Diaconescu
I know my answer is "a bit" late, but I had to share this:
我知道我的回答“有点”晚了,但我不得不分享这个:
Just discovered LinqPadand it's AMAZING (not to mention free).
Can't believe I've written Linq for so long without knowing about this tool.
刚刚发现了LinqPad,它太棒了(更不用说免费了)。
不敢相信我写了这么久 Linq 却不知道这个工具。
As far as I understand, it's the work of the author(s?) of O'Reilly's "C# 3.0 in a Nutshell"and "C# 4.0 in a Nutshell".
据我了解,这是 O'Reilly 的“C# 3.0 in a Nutshell”和“C# 4.0 in a Nutshell”的作者的作品。
回答by Michael Sorens
When I looked around recently for answers to the very same question I found some intriguing hints here and there but no cohesive narrative really digging into answering the question. So I wrote one myself and it was just published on Simple-Talk.com (LINQ Secrets Revealed: Chaining and Debugging). You might need to register to read the article (site seems to be going through some changes in recent days) so here are the highlights of the article:
当我最近环顾四周寻找同一问题的答案时,我在这里和那里发现了一些有趣的提示,但没有真正深入地回答这个问题的有凝聚力的叙述。所以我自己写了一个,它刚刚在 Simple-Talk.com 上发布(LINQ Secrets Revealed: Chaining and Debugging)。您可能需要注册才能阅读这篇文章(最近几天网站似乎发生了一些变化)所以这里是文章的重点:
(1) In LINQPad: Use its extraordinary Dump() method. You can inject this at one or more points in a LINQ chain to see your data visualized in an amazing clean and clear fashion.
(1) 在 LINQPad 中:使用其非凡的 Dump() 方法。您可以在 LINQ 链中的一个或多个点注入它,以惊人的干净清晰的方式查看您的数据。
(2) In Visual Studio: Embed nop statements in the middle of your LINQ chain so you can set breakpoints. Note the return statement must be on its own line to set a breakpoint in Visual Studio. (Thanks to Eric White's blog entry Debugging LINQ Queriesfor this tip.)
(2) 在 Visual Studio 中:在 LINQ 链的中间嵌入 nop 语句,以便您可以设置断点。请注意 return 语句必须在其自己的行上才能在 Visual Studio 中设置断点。(感谢 Eric White 的博客文章调试 LINQ 查询对此技巧。)
.Select(z =>
{return z;}
)
(3) In Visual Studio: Inject calls to the Dump() extension method I present in my article to allow logging. I started with Bart De Smet's Watch() method in his informative article LINQ to Objects – Debuggingand added some labeling and colorization to enhance the visualization, though still it pales in comparison to LINQPad's Dump output.
(3) 在 Visual Studio 中:注入对我在文章中介绍的 Dump() 扩展方法的调用以允许日志记录。我从 Bart De Smet 的信息文章LINQ to Objects – Debugging 中的 Watch() 方法开始,并添加了一些标签和着色以增强可视化效果,尽管与 LINQPad 的 Dump 输出相比仍然相形见绌。
(4) Finally, (yes I am enamored of LINQPad's Dump method!) bring LINQPad's visualization right into Visual Studio with Robert Ivanc's LINQPad Visualizeradd-in. Not a perfect solution (no support yet for VS2010, requires classes to be serializable, some rendering issues) but it is quite useful.
(4) 最后,(是的,我很喜欢 LINQPad 的 Dump 方法!)使用 Robert Ivanc 的LINQPad Visualizer插件将 LINQPad 的可视化直接引入 Visual Studio 。不是一个完美的解决方案(尚不支持 VS2010,需要类可序列化,一些渲染问题)但它非常有用。
2016.12.01 Update
2016.12.01 更新
Just published on Simple-Talk.com is the sequel to the above article: LINQ Debugging and Visualization. This article provides thorough coverage of the new LINQ debugging capability of the OzCode extension for Visual Studio 2015. OzCode finally makes LINQ debugging easy and powerful. (And, no, I do notwork for OzCode :-).
刚刚在 Simple-Talk.com 上发表的是上述文章的续篇:LINQ 调试和可视化。本文全面介绍了 Visual Studio 2015 的 OzCode 扩展的新 LINQ 调试功能。OzCode 最终使 LINQ 调试变得简单而强大。(而且,不,我不为 OzCode 工作 :-)。
回答by SleepyBoBos
Horse Apples!
马苹果!
Resharper (which I love) suggested I change this
Resharper(我喜欢)建议我改变这个
foreach (BomObservation initialObservation in initialObservations)
{
if(initialObservation.IsValid() && !initialObservation.IsStationOnly)
mappableObservations.Add(initialObservation);
}
to this
对此
initialObservations.Where(observation => observation.IsValid() && !observation.IsStationOnly).ToList();
Yeh it's sexy and sleek but stepping through it and debugging it? You just can't do it. I am going back to foreach for this one.
是的,它既性感又时尚,但要逐步完成并调试它?你就是做不到。我要回到 foreach 来解决这个问题。
I love LinqPad too and I do think Linq is pretty awesome in a 'one ring to rule them all' sort of way, but in this scenario I lose something.
我也喜欢 LinqPad,我确实认为 Linq 在“一环统治他们所有人”方面非常棒,但在这种情况下我失去了一些东西。
回答by Tomasz Chudzik
I know this is and old question but I have found other solutions that may be useful for somebody. I've struggled with the same problem when debugging LINQ queries. There are 2 good ways how you can debug them.
我知道这是一个老问题,但我找到了其他可能对某人有用的解决方案。我在调试 LINQ 查询时遇到了同样的问题。有两种很好的方法可以调试它们。
One way: Change lambda expressions to body expressions. This enables you to place a breakpoint inside. Also you can set some conditions for these breakpoint when you right-click on them so it gives you lots of possibilities. Example:
一种方法:将 lambda 表达式更改为正文表达式。这使您可以在内部放置断点。您还可以在右键单击这些断点时为这些断点设置一些条件,以便为您提供很多可能性。例子:
// Instead of this:
var names = new List<string> { "Anna", "Tom", "Jerry" };
var namesLength = names.Select(name => name.Length);
// Use this:
var names = new List<string> { "Anna", "Tom", "Jerry" };
var namesLength = names.Select(name =>
{
return name.Length; // Set breakpoint here
});
Another way: Use Quick Watch in Visual Studio. How? In the example above place a breakpoint where your LINQ query is. When the code stops, select the entire LINQ query with your mouse, right-click on it and select Quick Watch... . It produces the result of any query you place in there using the actual data you have in your program. It supports IntelliSense, too. One tip: It's usually useful to put a .ToList() at the end of your query in Quick Watch to see the results.
另一种方法:在 Visual Studio 中使用 Quick Watch。如何?在上面的示例中,在 LINQ 查询所在的位置放置一个断点。当代码停止时,用鼠标选择整个 LINQ 查询,右键单击它并选择 Quick Watch... 。它使用您在程序中拥有的实际数据生成您放置在其中的任何查询的结果。它也支持智能感知。提示:在 Quick Watch 中将 .ToList() 放在查询末尾以查看结果通常很有用。