Blog - Title

Debugging LINQ Queries

Debugging LINQ Queries

  • Comments 11

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 TOC
The 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.

Leave a Comment
  • Please add 4 and 1 and type the answer here:
  • Post
  • PingBack from http://www.tmao.info/debugging-linq-queries/

  • Hi Eric,

    I'm always reading your posts.

    This was a great tip.

    Thanks for sharing your knowledge,

    Leniel Macaferi

  • Thanks, Leniel  :)

  • > ... and you can’t set a breakpoint mid-expression.

    Actually, yes, you can! (Though few people seem to know it, and personally, I've only found out about a month ago.)

    Here's how: you set the breakpoint, then right-click it, and open "Location". In the dialog that opens, you set the "Line" and "Character" values to match the first character of the subexpression you want to break on. Et voila!

    This doesn't work all the time; in particular, it does not work for chained method calls - can't break on an individual method in the chain - and array/collection initializer. It also doesn't work if the subexpression is just a lone variable reference - it will then break on the outer expression instead (which is annoying in e.g. "foreach" or "from", where it is typically the case).

    However, it does fully work for LINQ queries written using syntactic sugar - you can break on the subexpression in "let", "where", "group by", "order by", "select" etc. It also works for the result expression part of the expression lambdas, so it can equally well be used for your specific LINQ chain-call example.

  • @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.

    -Eric

  • > 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.

    Try setting it at the start of the body of the lambda expression rather than at the start of Select/Where/GroupBy method call; i.e. for your example, you want to set it on ".GroupBy(i => i)" - so set it to that line number, and column number corresponding to the second "i".

  • I encountered a nice article by Eric White that explains how to debug Linq queries. Sum it up for me

  • 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

                   };

  • 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.

  • This is fantastic! never thought to do this, but damn if it is going to be helpful. Thanks for the post!

  • You can indeed set a breakpoint on a lambda expression, just with the mouse highlight the expression and press f9

Page 1 of 1 (11 items)