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.