2015-09-16 28 views
6

Powiedz, że mam to, gdzie chcę, aby każda osoba w grupie 42, ale chcę uzyskać IQuableable każdego unikalnego imienia w bazie danych (PS - wiem, że mogę nazwać AsQueryable() po Select, ale to nie jest to, co jestem zainteresowany w tym - Chcę baza do wykonania, a nie odrębny program):EF - DistinctBy na IQueryable?

MyEfContextContainer db = new MyEfContextContainer(); 
IQueryable<string> uniqueFirstNames = 
    db.People 
    .Where(x=> x.GroupId == 42) 
    .DistinctBy(c=> c.FirstName) 
    .Select(c=> c.FirstName); 

z tego co mogę powiedzieć o tym, jak EF/LINQ do podmiotów obsługuje metodę rozszerzenia DistinctBy, zapytanie jest sklep wykonywane po wywołaniu DistinctBy i wyświetleniu listy WSZYSTKICH elementów w bazie danych zgodnych z Where, a następnie C# zwraca wartość IEnumberable z metody DistinctBy, która jest zgodna z wyrażeniem wysłanym do DistinctBy.

Jeśli na liście znajduje się miliony nazw, jest to bardzo nieefektywne.

Jestem zainteresowany, aby móc to zrobić skutecznie, mając nadzieję, że zapytanie o sklep zwróci zestaw wyników wszystkich unikalnych FirstNames w tabeli. Mogę na przykład chcieć zwrócić ten IQueryable jako część repozytorium, gdzie ze względów wydajności nie jest w porządku, aby miliony przedmiotów zostały pobrane i przetworzone przez DistinctBy, aby zwrócić unikalne wartości. Zwiększyłoby to czas przetwarzania żądania do niedopuszczalnego poziomu.

Czy jest jakiś sposób to zrobić? Czy czegoś brakuje? To tylko prosty przykład, oczywiście w rzeczywistych aplikacjach obiekty bardziej złożone niż ciąg byłyby przedmiotem zapytania do repozytorium.

Odpowiedz

3

Z IQueryable trzeba to zrobić samemu: DistinctBy metoda

db.People 
    .Where(x => x.GroupId == 42) 
    .GroupBy(c => c.FirstName) 
    .Select(g => g.FirstOrDefault()); 

MoreLinq jest metoda rozszerzenie na IEnumerable<T>, więc nie przyjąć IQueryable<T>, ale wewnątrz metody działa jako IEnumerable<T>. Jest to taki sam efekt, jak robi db.People.AsEnumerable().DistinctBy()

+0

Mam, wiem, że mogę to zrobić, ale nie jestem pewien, czy to pasuje do mojego przypadku użycia ... pozwól mi rzucić okiem. – Pugz

5

pisałem tego rozszerzenia:

public static IQueryable<TSource> DistinctBy<TSource, TKey> (this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector) 
    { 
     return source.GroupBy(keySelector).Select(x => x.FirstOrDefault()); 
    } 

celu dokonania wyboru w oparciu o odrębną własność, np Chyba zadzwonię:

res = res.DistinctBy(x => x.Id);