2012-01-24 31 views
8

Chciałbym pogrupować moje zapytanie LINQ przez ItemNumber i zwrócić całą tabelę z całkowitą wartością Quantity.Grupowanie wyrażeń Lambda przez C#

Example: 
ItemNumber - ItemName - Quantity 
100   Item1  1 
150   Item2  2 
100   Item1  2 
200   Item3  1 
150   Item2  2 

Should be: 
ItemNumber - ItemName - Quantity 
100   Item1  3 
150   Item2  4 
200   Item3  1 

To jest kwerenda Próbuję grupy:

public IQueryable<WebsiteOrderStatus> GetOrderStatusByAccountNumberWithoutDeleted 
     (string accountNumber) 
{ 
    return db.WebsiteOrderStatus 
      .Where(x => x.AccountNumber == accountNumber && x.LastUpdatedStatus != 1); 
} 

I mój najlepszy wynik do tej pory (to nie można skompilować choć):

public IQueryable<IGrouping<Int32?, WebsiteOrderStatus>> lol(string accountNumber) 
{ 
    db.WebsiteOrderStatus 
     .Where(x => x.AccountNumber == accountNumber && x.LastUpdatedStatus != 1) 
     .GroupBy(g => g.ItemNumber) 
     .Select(g => new 
        { 
         g.Key.ItemNumber, 
         Column1 = (Int32?)g.Sum(p => p.Quantity) 
        }); 
} 

EDIT:

Dzięki za odpowiedzi wszystkim, muszę się z tym zmierzyć. Te anonimowe typy są dość trudne do pracy z moim zdaniem, więc znalazłem inne rozwiązanie.

Zrobiłem inną metodę, która sumuje ilość elementów użytkowników i zgrupowuje pierwszą.

public IQueryable<WebsiteOrderStatus> GetOrderStatusByAccountNumberWithoutDeleted(string accountNumber) 
{ 
    return db.WebsiteOrderStatus.Where(x => x.AccountNumber == accountNumber && x.LastUpdatedStatus != 1).GroupBy(x => x.ItemNumber).Select(grp => grp.First()); 
} 

public int GetQuantityOfUsersItem(string accountNumber, string itemNumber) 
{ 
    return db.WebsiteOrderStatus.Where(x => x.ItemNumber == itemNumber && x.AccountNumber == accountNumber).Sum(x => x.Quantity); 
} 

Na stronie, na której mam GridView zrobiłem:

var query = websiteOrderStatusRep.GetOrderStatusByAccountNumberWithoutDeleted(AppSession.CurrentLoginTicket.AccountNumber).Select(x => new { x.ItemName, x.ItemNumber, x.FormatName, x.Price, x.Status, x.Levering, Quantity = websiteOrderStatusRep.GetQuantityOfUsersItem(x.AccountNumber, x.ItemNumber)}); 
+1

Nie wiem, co jeszcze jest źle, ale przynajmniej, ty” ponownie brakuje "powrotu" w drugiej próbce. – Ani

+0

Jaki jest błąd kompilacji, który otrzymujesz? –

+1

Prawdopodobnie próbuje traktować g.Key jako obiekt, podczas gdy to tylko int. Jeśli chce nazwy przedmiotu w wyniku, to będzie musiał również przechowywać go w kluczowym obiekcie (i uczynić klucze obiektem, który jest porównywalny) lub odczytać go z pierwszego wpisu w grupie enumberator, jak sądzę. – Rup

Odpowiedz

10
public IQueryable<IGrouping<Int32?, WebsiteOrderStatus>> lol(string accountNumber) 
{ 
    db.WebsiteOrderStatus 
     .Where(x => x.AccountNumber == accountNumber && x.LastUpdatedStatus != 1) 
     .GroupBy(g => g.ItemNumber) 
     .Select(g => new 
        { 
         ItemNumber = g.Key, 
         ItemName = g.First().ItemName, 
         Count = g.Sum(item => item.Quantity) 
        }); 
} 
3

myślę Select powinno być:

.Select(g => new 
       { 
        ItemNumber = g.Key, 
        Column1 = (Int32?)g.Sum(p => p.Quantity) 
       }); 

Uwaga zmiana w pierwszej linii anonimowy typ. Kluczem do grupowania jest już numer pozycji.

5

Jedyny problem widzę z zapytaniu są

  1. Brakujące return oświadczenie za komentarze
  2. select oświadczenie powinno być:

-

.Select(g => new { 
     ItemNumber = g.Key, 
     Total = g.Sum(p => p.Quantity) 
    }); 

EDIT: Jeśli chcesz uzyskać, powiedzmy Nummer artykułu i ItemName, w powstałym obiektem, należy także grupa na tych polach

db.WebsiteOrderStatus 
    .Where(x => x.AccountNumber == accountNumber && x.LastUpdatedStatus != 1) 
    .GroupBy(g => new { g.ItemNumber, g.ItemName }) 
    .Select(g => new 
       { 
        ItemNumber = g.Key.ItemNumber, 
        ItemName = g.Key.ItemName, 
        Count = g.Sum(item => item.Quantity) 
       }); 
+0

Wygląda na to, że wracają tylko ItemNumber i Total. Potrzebuję całej tabeli tylko z kolumną o nazwie total, która zawiera sumę dla ilości – KLIM8D

+0

@ KLIM8D - Zobacz aktualizację – Jamiec

+0

okej, więc każdy obiekt, który chcę uzyskać w wyniku musi być w grupie. W rzeczywistości mam 5 innych pól w tabeli, czy może istnieć lepszy sposób robienia tego grupowania, inne niż wszystkie pola, których potrzebuję, muszą być zawarte w groupby? – KLIM8D

7
public IQueryable<OrderStatus > lol(string accountNumber) 
{ 
    return db.WebsiteOrderStatus 
     .Where(x => x.AccountNumber == accountNumber && x.LastUpdatedStatus != 1) 
     .GroupBy(g => g.ItemNumber) 
     .Select(g => 
       new OrderStatus //This is your custom class, for binding only 
       { 
        ItemNumber = g.Key, 
        ItemName = g.First().ItemName, 
        Quantity = g.Sum(g => g.Quantity) 
       } 
     ); 
} 
+0

Jesteśmy prawie na miejscu - bez błędów, dopóki nie próbuję wiązać moje zapytanie do gridview. Otrzymuję ten wyjątek: System.NotSupportedException: Jawna konstrukcja typu jednostki "GWportal.BusinessLayer.Repository.WebsiteOrderStatus" w zapytaniu jest niedozwolona. – KLIM8D

+2

'Jednostki mogą być tworzone poza zapytaniami i wstawiane do magazynu danych przy użyciu DataContext. Możesz następnie pobrać je za pomocą zapytań. Jednak nie możesz tworzyć encji jako części zapytania. W tym przypadku będziesz musiał stworzyć niestandardową klasę do wiązania i mapowania "WebsiteOrderStatus" do obiektu tej klasy. –

2

Nie można użyć anonimowego typu na typ zwracanej wartości. Więc nigdy nie skompilujesz kodu.

Również twój wyrażeń linq ma typ IQueryable < [typ anonimowy]> typ wyniku.

wierzę, że można zrobić coś takiego:

public IQueryable<OrderStatus> lol(string accountNumber) 
{ 
    db.WebsiteOrderStatus 
     .Where(order => order.AccountNumber == accountNumber && order.LastUpdatedStatus != 1) 
     .GroupBy(order => order.ItemNumber) 
     .Select(grouping => new OrderStatus //This is your custom class, for binding only 
        { 
         ItemNumber = grouping.Key, 
         ItemName = grouping.First().ItemName, 
         Quantity = grouping.Sum(order => order.Quantity) 
        }); 
} 

`ve stałe moją odpowiedź też :)

+0

Dlaczego nie można użyć typów anonimowych jako wartości zwracanej. – Jamiec

+1

Jak określasz to podpisem metody? –

+0

MSDN: Nie można zadeklarować pola, właściwości, zdarzenia lub typu zwracanego metody jako typu anonimowego. Podobnie nie można zadeklarować formalnego parametru metody, właściwości, konstruktora lub indeksu jako posiadającego typ anonimowy. Aby przekazać anonimowy typ lub kolekcję zawierającą anonimowe typy, jako argument do metody, można zadeklarować parametr jako obiekt typu. Jednak czyniąc to pokonuje cel silnego pisania. Jeśli musisz przechowywać wyniki zapytania lub przekazywać je poza granicę metody, rozważ użycie zwykłej nazwanej struktury lub klasy zamiast typu anonimowego. –

Powiązane problemy