2010-09-02 3 views
4

Я новичок в LINQ и не хочу этого делать, и этот код трудно поддерживать.Этот запрос LINQ слишком длинный?

Как вы думаете, этот запрос LINQ слишком длинный?

IList<ListViewItem> data = runAnalysis.PassAnalyses.Cast<PassAnalysis>(). 
    Select(passAnalysis => passAnalysis.GetValue(PeakStatistics.PeakStatisticsProperty)). 
    SelectMany(peakStatistics => peakStatistics.Statistics. 
    Where(statisticsBase => statisticsBase.Name == statisticType). 
    Select(statisticsBase => new ListViewItem {Content = statisticsBase})).ToList(); 
+0

делает все, что в 1 запрос всегда лучше, чем в много маленьких .... особенно с linq. – Stefanvds

+6

Почему? Ничто из этого не выполняется, пока вы не перечислите результаты. – Mark

ответ

10

Я бы сказал, что сложно из-за вложенности - но на самом деле не нужно. Вот пример запроса, который даст те же результаты (я думаю), но проще ...

IList<ListViewItem> data = runAnalysis.PassAnalyses 
     .Cast<PassAnalysis>() 
     .Select(pass => pass.GetValue(PeakStatistics.PeakStatisticsProperty)) 
     .SelectMany(peakStats => peakStats.Statistics) 
     .Where(statisticsBase => statisticsBase.Name == statisticType) 
     .Select(statisticsBase => new ListViewItem {Content = statisticsBase}) 
     .ToList(); 

Без вложенности, это легко увидеть, как преобразование идет:

  • Start с PassAnalyses
  • в ролях каждый элемент в PassAnalysis
  • Выберите PeakStatistics
  • от каждого элемента, выберите все статистики внутри нее, и придавить эту последовательность
  • фильтр любой статистики с неправильным именем
  • Преобразование каждого результата в ListViewItem
  • Преобразовать всю последовательность в список

На данный момент, это легко преобразовать его в выражение запроса:

IList<ListViewItem> data = 
    (from PassAnalysis pass in runAnalysis.PassAnalyses 
    from statsBase in pass.GetValue(PeakStatistics.PeakStatisticsProperty) 
          .Statistics 
    where statsBase.Name == statisticType 
    select new ListViewItem { Content = statsBase }) 
    .ToList(); 

Обратите внимание, что я выбрал первый вариант Select и SelectMany; вы можете использовать предложение let, если хотите. Также я использовал явный тип для переменной диапазона pass, чтобы заставить компилятор генерировать вызов Cast<PassAnalysis >().

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

Вызов ToList() в конце несколько некрасиво, как нет никакого выражения запроса синтаксис для этого ... но вы можете использовать промежуточную переменную для этого:

var query = ...; 
IList<ListViewItem> data = query.ToList(); 
+0

Это замечательно, очень информативно, спасибо. – mkocubinski

7

IMO запрос в порядке, хотя он выглядит несколько плотным. Вы можете переформатировать это немного более просторнее:

var query = from analysis in runAnalysis.PassAnalyses.Cast<PassAnalysis>() 
      let value = analysis.GetValue(PeakStatistics.PeakStatisticsProperty) 
      from statistic in value.Statistics 
      where statistic.Name == statisticType 
      select new ListViewItem { Content = statistic }; 

IList<ListViewItem> data = query.ToList(); 
+4

+1 синтаксис sql делает его ПУТЕМ более легким для чтения ... –

+0

По какой-то причине мне нравится метод цепочки лучше. – ChaosPandion

+0

@ChaosPandion: Вероятно, поэтому у нас есть как на C# :-) – dtb

Смежные вопросы