Zapytanie LINQ

PO
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 92
0

Witajcie, mam do napisania zapytanie , które ma wyświetlić unikatowe rekordy , które pojawiają się w bazie przynajmniej raz. Napisałem zapytanie do SQLa - powinno ono wyglądać tak:

Kopiuj
SELECT a.Name, a.ProductID
	FROM Production.Product a
    INNER JOIN Production.ProductReview b
    ON a.ProductID =  b.ProductID
	group by a.Name , a.ProductID 
	having count(a.ProductID) >=1

Chciałbym powyższe zapytanie przetworzyć na LINQ Udało mi się napisać coś takiego:

Kopiuj
 var query = from product in db.ProductReviews
                            join productreviews in db.ProductReviews
                            on product.ProductID equals productreviews.ProductID
                            group product by product.ProductID  into grp
                            where grp.Count() >= 1
                            select new { grp };

Niestety nie do końca działa to tak jak powinno. Ogólnie chciałbym, żeby zapytanie przypisać do List<Product> a nie do vara, ewentualnie zostawić już tego vara, ale wyświetlić wszystkie pola z tabeli Product a nie tylko ProductID. Mi już kończą się pomysły , z góry dzięki za pomoc ! W załączeniu schemat tych dwóch tabeli.

somekind
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
0

Ten Twój var to w tym miejscu najprawdopodobniej IGrouping<int, Product> i generalnie możesz go traktować jako IEnumerable<Product>.

PO
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 92
0

OK rzeczywiście , jak zrezygnuję z typu anonimowego i wybiorę select grp to mam:

Kopiuj
 IQueryable<IEnumerable<Product>>

I w sumie chyba mogłoby tak być. Chciałbym jednak wybrać wszystkie pola z tabeli Product a wybiera mi się tylko pole, które podlega grupowaniu, czyli ProductID. Jakiś pomysł?

somekind
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
2

O ile dobrze rozumiem, to potrzebujesz tam po prostu SelectMany(x => x.ToList()), ale nie wiem jak to zapisać w LINQ expression.

Tu masz przykład analogicznego problemu (spłaszczenie kolekcji po grupowaniu) w normalnym zapisie:

Kopiuj
var members = typeof (string).GetMembers()
    .GroupBy(x => x.MemberType)
    .SelectMany(x => x.ToList());
ŁF
  • Rejestracja: dni
  • Ostatnio: dni
1

sql:

Kopiuj
GROUP BY a.Name , a.ProductID

linq:

Kopiuj
group product by product.ProductID  into grp

Po pierwsze potrzebujesz grupować po dwóch polach, grupujesz po jednym.
Po drugie Twoim sql nie uzyskasz tego, co chcesz, więc w linq tym bardziej. Jeśli chcesz otrzymać listę produktów, które mają chociaż jedno review, to zrobisz to inaczej:

Kopiuj
products.Where(p => p.ProductReviews.Any())

albo

Kopiuj
from p in products
where products.ProductReviews.Any()
select p

albo - jeśli nie masz FK (schemat z bazy mówi, że masz) albo nie masz ich zamapowanych do ORM:

Kopiuj
products.Where(p => productReviews.Any(pr => pr.ProductId == p.Id))

Z Twojego zapytania można zrobić takie rozwiązanie (czysto akademickie, bo zawierające wiele zbędnych rzeczy i tragiczne, jeśli chodzi o wydajność):

Kopiuj
var productIds = (from product in db.ProductReviews
    join productReviews in db.ProductReviews
    on product.ProductID equals productReviews.ProductID
    group product by product.ProductID  into groupedProducts
    where groupedProducts.Count() >= 1 // IMHO zbędne, bo join productReviews nie jest left joinem, więc produkty nieposiadające review nie znajdą się w wynikach
    select groupedProducts.Key.Id
).ToList();
var productsThatHaveReview = db.Products.Where(p => productIds.Contains(p.Id)).ToList();
Kopiuj
PO
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 92
0

Dzięki wielkie!

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.