2012-01-18 10 views
7

Mam oświadczenie LINQ który sumowaniu wartości wielu kolumnach, każdy zaczynający się na „HH”, chociaż istnieją inne kolumny dostępne:Ugly LINQ oświadczenie, lepszy sposób?

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

Czy istnieje jakiś sposób, aby uporządkować tę górę? Muszę wykonać wiele wariacji tego (różnymi metodami), aby w razie potrzeby wyeliminować wiele "puchu".

Chciałbym również zadzwonić pod numer .GetValueOrDefault() w każdej kolumnie, ale obecnie usunąłem to z powodu bałaganu za wyjątkiem dwóch ostatnich kolumn.

Sugestie bardzo doceniane!

+0

Czy wartości, które należy dodać, są zawsze takie same? Więc zawsze HH01, HH16, HH17, ...? –

+0

Z jakiego dostawcy LINQ korzystasz? – Oded

+0

@WouterdeKort: Zgaduję, że nie, ponieważ musi zmieniać wariacje ... – FarligOpptreden

Odpowiedz

2

Chyba można użyć Refleksje na to:

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; 
} 

a następnie używać go tak:

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

Kodeks nie jest testowany

+1

To nie zadziała, ponieważ dostawca nie wie, jak przetłumaczyć słowo "GetHHSum" na SQL. –

+0

Edytowałem swoją odpowiedź. Nie jest to próba przetłumaczenia go na SQL, ale wystarczy użyć rozszerzenia pomocniczego Linq, aby wybrać właściwe rzeczy. –

+1

Będzie działać, jeśli zmienisz "List" na "ToList". –

2

może się mylę, bo nie znam twoich danych, ale wydaje mi się, że nie są w pełni znormalizowane (powtarzające się atrybuty). Możesz rozważyć przejście do trzeciej postaci normalnej - w ten sposób utwórz osobną tabelę, która będzie zawierała jedną wartość po wierszu - a następnie dołącz do twoich 2 tabel w zapytaniu linq.

Zapytanie o link będzie wyglądać znacznie lepiej, a później będzie można zmienić pola HH bez zmiany zapytań.

+0

Dane nie mają nic wspólnego ze mną, mam tylko tabelę bazy danych (której nie mogę zmienić ani zmodyfikować w żaden sposób) i muszę wyodrębnić dane tak jak jest –

+0

Nie ma nic w opublikowany kod, który pokazuje, że dane nie są znormalizowane – Cosmin

+0

Cosmin: rzeczywiście moja odpowiedź opiera się na wielu założeniach. co doprowadziło mnie do użycia terminu "kolumna" w pytaniu. Ponadto, z doświadczeniem łatwo jest rozpoznać ten rodzaj problemów i rozwiązać je w katalogu głównym (dane) – Skyp

1

Jedną z sugestii jest refaktoryzacja powyższego kodu w celu użycia łańcuchów metod LINQ i lambdas (osobiste preferencje), a następnie wyodrębnienie wybranej lambdy w osobną metodę. Na przykład:

// 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() 
} 

Ponadto jeśli chcesz zadzwonić GetValueOrDefault() na każdej nieruchomości HHxx można owinąć to w kolejnej funkcji pomocnika. to naprawdę sprowadza się do preferencji kodu. Który wolisz? Widzisz .GetValueOrDefault() na końcu każdego dostępu do właściwości lub funkcji wokół niego? na przykład

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

staje

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

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

Osobiście po prostu iść z zamawianiu mój kod HHxx + HHyy w kolumnach i nazywając .GetValueOrDefault() na każdej z nich. Jeśli zostanie wprowadzona metoda pomocnicza, to przynajmniej jest zapisana tylko raz, nawet jeśli jest pełna.

Pozdrawiam,

Powiązane problemy