Как отладить оператор LINQ - PullRequest
       29

Как отладить оператор LINQ

40 голосов
/ 23 сентября 2008

У меня есть оператор Linq to objects

 var confirm = from l in lines.Lines 
 where (l.LineNumber == startline.LineNumber) || (l.LineNumber == endline.LineNumber) 
 select l;

Подтверждающий объект возвращает «Нулевой объект или нет ссылки» в System.Linq.Enumerable.WhereListIterator`1.MoveNext ()

Если бы результат запроса был пустым, он просто вернул бы пустой перечислитель. Я точно знаю, что в заявлении нет нулевых объектов. Можно ли пройти через оператор LINQ, чтобы увидеть, где он падает?

РЕДАКТИРОВАТЬ Когда я сказал Я точно знаю, что нет нулевых объектов Оказывается, я лгал: [, но вопрос остается, хотя я предполагаю ответ будет «ты не можешь на самом деле»

LINQPad - хорошая идея, я использовал ее, чтобы научить себя LINQ, но я могу начать смотреть на нее снова как на инструмент для отладки, слэша и записи

Ответы [ 9 ]

30 голосов
/ 04 апреля 2009

Да, действительно возможно приостановить выполнение на полпути через запрос linq.

Преобразуйте ваш linq в стиль запроса, используя лямбда-выражения, и вставьте оператор Select, который возвращает себя где-то после точки в linq, которую вы хотите отладить. Некоторый пример кода сделает его более понятным -

        var query = dataset.Tables[0].AsEnumerable()
            .Where (i=> i.Field<string>("Project").Contains("070932.01"))
 //         .Select(i =>
 //         {return i;}
 //           )
            .Select (i=>i.Field<string>("City"));

Затем раскомментируйте закомментированные строки. Убедитесь, что {return i;} находится в отдельной строке и вставьте туда точку отладки. Вы можете поместить этот выбор в любой момент длинного и сложного запроса linq.

28 голосов
/ 23 сентября 2008

Я не уверен, можно ли отлаживать с VS, но я считаю LINQPad весьма полезным. Это позволит вам выводить результаты каждой части запроса LINQ.

17 голосов
/ 23 сентября 2008

Вы должны иметь возможность установить точку останова для выражения в предложении where вашего оператора LINQ.

В этом примере поместите курсор в любом месте следующего раздела кода:

(l.LineNumber == startline.LineNumber) || (l.LineNumber == endline.LineNumber)

Затем нажмите F9 или используйте меню или контекстное меню, чтобы добавить точку останова.

При правильной настройке только приведенный выше код должен иметь форматирование точки останова в редакторе, а не весь оператор LINQ. Вы также можете посмотреть в окне контрольных точек, чтобы увидеть.

Если вы установили его правильно, вы будете каждый раз останавливаться на функции, которая реализует вышеуказанную часть запроса.

15 голосов
/ 10 декабря 2010

Я написал исчерпывающую статью, посвященную этому вопросу, опубликованную на Simple-Talk.com ( Раскрытые секреты LINQ: создание цепочек и отладка ) еще в 2010 году:

Я говорю о LINQPad (как упоминалось ранее OwenP) как о замечательном инструменте external для Visual Studio. Обратите особое внимание на его необычный метод Dump (). Вы можете добавить это в одну или несколько точек в цепочке LINQ, чтобы ваши данные были удивительно чистыми и понятными. Хотя LINQPad очень полезен, он является внешним по отношению к Visual Studio. Поэтому я также представляю несколько методов, доступных для использования в Visual Studio, потому что иногда просто не практично переносить кусок кода в LINQPad:

(1) Внедрить вызовы метода расширения Dump (), который я представляю в своей статье, чтобы разрешить ведение журнала. Я начал с метода Bart De Smet's Watch () в его информативной статье LINQ to Objects - Debugging и добавил некоторую маркировку и раскрашивание для улучшения визуализации, хотя он по-прежнему бледнеет по сравнению с выводом дампа LINQPad.

(2) Добавьте визуализацию LINQPad прямо в Visual Studio с помощью надстройки LINQPad Visualizer Роберта Иванка. Не уверен, что это было из-за моего подталкивания :-), но пара неудобств, которые присутствовали, когда я писал свою статью, теперь все замечательно устранены в последней версии. Он имеет полную поддержку VS2010 и позволяет вам исследовать любой объект, который вам нравится при отладке.

(3) Вставьте операторы nop в середину цепочки LINQ, чтобы вы могли устанавливать точки останова, как описано ранее Amazing Pete.

2016.12.01 Обновление

И я только что написал продолжение вышеприведенной статьи под названием Отладка и визуализация LINQ , которая показывает, что настоящая возможность отладки LINQ наконец-то появилась в Visual Studio 2015 с готовой к выпуску новая функция в OzCode. Ответ Дрора на этот вопрос показывает его проблеск, но я призываю вас прочитать мою новую статью для углубленного «как». (И я не работает для OzCode. :-)

6 голосов
/ 13 сентября 2016

[Отказ от ответственности: я работаю в OzCode]

Проблема с LINQ заключается в том, что отладку трудно или невозможно - даже при работе с простыми запросами разработчик вынужден реорганизовать свой запрос в группу циклов foreach или использовать ведение журнала. Отладка LINQ поддерживается в готовящейся к выпуску версии OzCode (, в настоящее время доступной в качестве предварительного просмотра для раннего доступа ), и она помогает разработчикам также углубиться в свой код LINQ и точно определить те, которые трудно перехватить внутри запросы

Вот как будет выглядеть ваш запрос в OzCode: Debugging LINQ exception

5 голосов
/ 07 августа 2016

Можно войти внутрь выражения LINQ без установки каких-либо временных точек останова. Вам нужно войти в функцию, которая оценивает выражение LINQ, например ::

var confirm = from l in lines.Lines 
              where (l.LineNumber == startline.LineNumber)
                    || (l.LineNumber == endline.LineNumber) 
              select l;

 confirm.ToArray(); // Press F11 ("Step into") when you reach this statement

 foreach(var o in q) // Press F11 when "in" keyword is highlighted as "next statement"
    // ...
3 голосов
/ 23 сентября 2008

Судя по ошибкам, я бы посоветовал вам взглянуть на строку. Строки и убедиться, что ее перечислитель реализован правильно. Я думаю, что он возвращает ноль, когда не должен.

Да, и просто убедитесь, что объекты line и line.Lines не равны NULL или не возвращают NULL.

3 голосов
/ 23 сентября 2008

Проверьте трассировку стека исключений и посмотрите последний бит вашего кода, который был выполнен.

0 голосов
/ 20 февраля 2019

Хотя это не способ отладки, я бы предложил использовать следующее:

using (var db = new AppContext())
        {
            db.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
            // Rest of code
        }

Вы можете проверить окно вывода при отладке, чтобы увидеть SQL, сгенерированный из вашего запроса LINQ.

...