Debugging LINQ Queries
Debugging LINQ queries can be problematic. One of the reasons is that quite often, you write a large query as a single expression, and you can’t set a breakpoint mid-expression. Writing large queries in expression context is particularly powerful when using functional construction to form XML (or using the strongly typed DOM in Open XML SDK V2). This post presents a little trick that makes it easier to use the debugger with LINQ queries that are written using ‘method syntax’.
This blog is inactive.
New blog: EricWhite.com/blog
Blog TOCThe gist of the technique is to insert a call to the Select extension method in the middle of your query. You code the Select so that it projects exactly the same results as its source, but using a statement lambda expression If you place the return statement of the lambda expression on its own line, you can set a breakpoint and examine values as they make their way through the query.
The following is a query to split a string into words, convert the words to lower case, count the number of occurances of each word, and return the ten most used words:
var uniqueWords = text
.Split(' ', '.', ',')
.Where(i => i != "")
.Select(i => i.ToLower())
.GroupBy(i => i)
.OrderByDescending(i => i.Count())
.Select(i => new { Word = i.Key, Count = i.Count() })
.Take(10);
But if you set a breakpoint anywhere on the query, you see this:
Let’s say that you want to examine each group and see the group key and the count of items for each group. You can insert a Select statement, as follows:
var uniqueWords = text
.Split(' ', '.', ',')
.Where(i => i != "")
.Select(i => i.ToLower())
.GroupBy(i => i)
.Select(z => {
return z;
})
.OrderByDescending(i => i.Count())
.Select(i => new { Word = i.Key, Count = i.Count() })
.Take(10);
you can now set a breakpoint on the ‘return z’ statement, and examine each group in turn as they are yielded up by the GroupBy extension method:
You can see that the key is “on”, and that there are four items in the group.
After you are done debugging, you can remove the added call to Select.
Alternatively, you could convert any of the other lambda expressions to a statement lambda expression, format code so that a statement is on its own line, and then set a breakpoint.
Comments
Anonymous
November 06, 2008
PingBack from http://www.tmao.info/debugging-linq-queries/Anonymous
November 07, 2008
Hi Eric, I'm always reading your posts. This was a great tip. Thanks for sharing your knowledge, Leniel MacaferiAnonymous
November 07, 2008
Thanks, Leniel :)Anonymous
November 08, 2008
The comment has been removedAnonymous
November 09, 2008
@int19, I knew that there was a way to use the debugger more closely with LINQ queries that use query expressions (except that mainly I don't use query expressions). I tried to use your tip to set a breakpoint in the above chain (at a location that was not just a variable assignment), and wasn't successful - probably am doing something wrong. -EricAnonymous
November 09, 2008
The comment has been removedAnonymous
November 23, 2008
I encountered a nice article by Eric White that explains how to debug Linq queries. Sum it up for meAnonymous
December 03, 2008
It doesn't work. I can't use it on queries like these. var data = from DataSet1.OrderRow orderRow in ds.Order from DataSet1.CustomerRow customerRow in ds.Customer from DataSet1.OrderDetailRow orderDetailRow in ds.OrderDetail where orderRow.ID == orderDetailRow.OrderID && orderRow.CustomerID == customerRow.ID select new { FullName = orderRow.CustomerRow.FirstName + " " + orderRow.CustomerRow.LastName, orderDetailRow.ItemPrice };Anonymous
December 08, 2008
frustrated, what doesn't work - Eric's proposal, or mine? Anyway, in LINQ comprehensions, you can set breakpoint to individual subexpressions in the way I've described in the comments above, but only so long as they are expressions, and not just range variable references.Anonymous
September 13, 2012
The comment has been removedAnonymous
June 18, 2014
You can indeed set a breakpoint on a lambda expression, just with the mouse highlight the expression and press f9