Отладка запросов 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.
Ответ 5
В этом сообщении в блоге есть некоторые очень перспективные методы для отладки LINQ to Objects.
Ответ 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 довольно классно в одном кольце, чтобы управлять всеми их способами, но в этом сценарии я что-то теряю.