Отладка запросов LINQ

В последнее время мы много работаем с LINQ, главным образом в смысле LINQ-to-Objects. К сожалению, некоторые из наших запросов могут быть немного сложными, особенно когда они начинают включать в себя несколько последовательностей. Трудно точно сказать, что происходит, когда вы получаете запросы, которые начинают выглядеть:

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();

и т.д. и т.д.

Даже когда вы отлаживаете, сложно сказать, кто что делает, кому и когда. За исключением безвозмездного вызова "ToList" на последовательностях, чтобы получить то, что я могу проверить более легко, есть ли у кого-нибудь хорошие предложения по отладке "сложного" LINQ?

Ответы

Ответ 1

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

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

Ответ 2

Я знаю, что мой ответ "немного" поздно, но мне пришлось поделиться этим:

Только что обнаружил LinqPad, и это УДИВИТЕЛЬНО (не говоря уже о бесплатном).
Не могу поверить, что я написал Linq так долго, не зная об этом инструменте.

Насколько я понимаю, это работа автора (s?) O'Reilly "С# 3.0 в двух словах" и "С# 4.0 в двух словах" .

Ответ 3

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

(1) В LINQPad: используйте свой необычный метод Dump(). Вы можете вставить это в одну или несколько точек в цепочке LINQ, чтобы увидеть, как ваши данные визуализируются удивительно чистым и понятным образом.

(2) В Visual Studio: вставьте nop-операторы в середине вашей линии LINQ, чтобы вы могли установить контрольные точки. Обратите внимание, что оператор return должен быть в своей строке, чтобы установить точку останова в Visual Studio. (Благодаря записи блога Eric Whites Отладка запросов LINQ для этого совета.)

.Select(z =>
{return z;}
)

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

(4) Наконец, (да, я влюблен в метод LINQPad Dump!) привожу визуализацию LINQPad прямо в Visual Studio с Робертом Иванком LINQPad Visualizer надстройка. Не идеальное решение (пока нет поддержки VS2010, требуется, чтобы классы были сериализуемыми, некоторые проблемы с рендерингом), но это очень полезно.

2016.12.01 Обновление

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

Ответ 4

Нет встроенных инструментов, о которых я знаю. Лучшее, что вы можете сделать, это разбить запрос в нескольких подзапросах и оценить эти подзапросы во время отладки. Хорошим сторонним инструментом является LINQPad.

Ответ 6

Лошадиные яблоки!

Resharper (который мне нравится) предложил мне изменить этот

foreach (BomObservation initialObservation in initialObservations)
{
    if(initialObservation.IsValid() && !initialObservation.IsStationOnly)
        mappableObservations.Add(initialObservation);
}

к этому

initialObservations.Where(observation => observation.IsValid() && !observation.IsStationOnly).ToList();

Он сексуальный и гладкий, но перешагивает его и отлаживает? Вы просто не можете этого сделать. Я возвращаюсь к foreach для этого.

Мне тоже нравится LinqPad, и я думаю, что Linq довольно классно в одном кольце, чтобы управлять всеми их способами, но в этом сценарии я что-то теряю.