Уродливое утверждение LINQ, лучший способ? - PullRequest
7 голосов
/ 18 января 2012

У меня есть оператор LINQ, который складывает значения нескольких столбцов, каждый из которых начинается с 'HH', хотя есть другие доступные столбцы:

//TODO Clean up this mess
var query1 = (from e in Data
                where e.SD == date
                select e).Select(x =>   x.HH01 + x.HH16 + x.HH17 + x.HH18 + x.HH19 + x.HH20 + x.HH21 + x.HH22 + x.HH23 +
                                        x.HH24 + x.HH25 + x.HH26 + x.HH27 + x.HH28 + x.HH29 + x.HH30 + x.HH31 + x.HH32 + 
                                        x.HH33 + x.HH34 + x.HH35 + x.HH36 + x.HH37 + x.HH38 + x.HH39 + x.HH40 + x.HH41 +
                                        x.HH42 + x.HH43 + x.HH44 +x.HH45 + x.HH46 + x.HH47 + x.HH48 + x.HH49.GetValueOrDefault()+
                                        x.HH50.GetValueOrDefault());

return query1.FirstOrDefault();

Есть ли способ привести это в порядок?Я должен сделать много вариаций этого (в разных методах), чтобы было много «пуха», если бы это могло быть.

Также я хотел бы вызвать .GetValueOrDefault() для каждого столбца,но в настоящее время я взял это из-за беспорядка за исключением последних двух столбцов.

Предложения очень ценятся!

Ответы [ 3 ]

2 голосов
/ 18 января 2012

Я могу ошибаться, потому что я не знаю ваших данных, но мне кажется, что они не полностью нормализованы (повторяющиеся атрибуты). Вы могли бы рассмотреть переход к 3-й форме нормально - таким образом создать / некоторую отдельную таблицу, которая будет содержать одно значение за строкой - и затем объединить две таблицы в вашем запросе linq.

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

2 голосов
/ 18 января 2012

Я думаю, вы можете использовать Reflections для этого:

double GetHHSum<T>(T x) where T : class
{
   double result = 0;

   var properties = typeof(T).GetProperties();
   foreach (var property in properties)
   {
       if (property.Name.StartsWith("HH"))
          sum += Convert.ToSingle(property.GetValue(x)).GetValueOrDefault();
   }

   return result;
}

И затем использовать это так:

return (from e in Data
        where e.SD == date
        select e).ToList().Select(x => GetHHSum(x)).FirstOrDefault();

Код не проверен

1 голос
/ 18 января 2012

Одним из предложений является рефакторинг приведенного выше кода для использования цепочек методов LINQ и лямбда-выражений (личное предпочтение), а затем выделение лямбда-выбора в отдельный метод. Например:

// Note select e and .Select(x => x..) is redundant. Only need one
var query1 = Data.Where(e => e.SD == date).Select(SumOfHValues);
return query1.FirstOrDefault();

// Note types are unclear in your question so I've put dummy placeholders
private static QueryResultType SumOfHValues(YourInputClassType x)
{
    // Nothing wrong with this syntactically, it will be faster than a 
    // reflection solution
    // 
    // Algorithmic code tends to have this sort of look & feel. 
    // You could make it more readable
    // by commenting exactly what the summation is doing and 
    // with a mathematical notation or link to documentation / web source
    return x.HH01 + x.HH16 + x.HH17 + x.HH18 + 
           x.HH19 + x.HH20 + x.HH21 + x.HH22 + 
           x.HH23 + x.HH24 + x.HH25 + x.HH26 + 
           x.HH27 + x.HH28 + x.HH29 + x.HH30 + 
           x.HH31 + x.HH32 + x.HH33 + x.HH34 + 
           x.HH35 + x.HH36 + x.HH37 + x.HH38 + 
           x.HH39 + x.HH40 + x.HH41 + x.HH42 + 
           x.HH43 + x.HH44 + x.HH45 + x.HH46 + 
           x.HH47 + x.HH48 + 
           x.HH49.GetValueOrDefault() +
           x.HH50.GetValueOrDefault()
}

Кроме того, если вы хотите вызывать GetValueOrDefault () для каждого свойства HHxx, вы можете заключить его в дополнительную вспомогательную функцию. это действительно сводится к предпочтениям кода. Какой ты предпочитаешь? Видя .GetValueOrDefault () в конце каждого доступа к свойству или функции вокруг него? например

return x.HH01 + x.HH16 + x.HH17 + x.HH18

становится

return Get(x.HH01) + Get(x.HH16) + Get(x.HH17) + Get(x.HH18) ... 

private static HClassType Get(HClassType input)
{ 
    return input.GetValueOrDefault();
} 

Лично я хотел бы просто заказать код HHxx + HHyy в столбцах и вызывать .GetValueOrDefault () для каждого. Если он помещен во вспомогательный метод, по крайней мере, его пишут только один раз, даже если он многословен.

С уважением,

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