Wpis z mikrobloga

#programowanie #csharp

Wróciłem ostatnio do czytania o IQueryable i mam pewne wątpliwości. Z jednej strony spotkałem się z informacją, że jeśli nie użyjemy AsQueryable, filtrowanie odbywa się na bazie danych, a z drugiej strony, że bez AsQueryable, ale z ToListAsync(), filtrowanie również działa na bazie danych. Przykład można znaleźć na Stack Overflow. To kiedy w końcu stosować AsQueryable i zwracać IQueryable ? Pośrednie rozwiązanie zaproponował tutaj na blogu używając query jako parametru.

Według autora filtrowane na bazie

context.MyLongWideTable // A table with many records and columns
.Where(x => x.Type == "type")
.Select(x => new { x.Name, x.CreateDate })

Tu według autora tylko where jest wykonany na bazie

context.MyLongWideTable
.Where(x => x.Type == "type").AsEnumerable()
.Select(x => new { x.Name, x.CreateDate.Date })

natomiast na stronie MS jest tak

var groupedHighlyRatedBlogs = await context.Blogs
.AsQueryable()
.Where(b => b.Rating > 3) // server-evaluated
.AsAsyncEnumerable()
.GroupBy(b => b.Rating) // client-evaluated
.ToListAsync();
  • 8
  • Odpowiedz
@smalczyk1: Jak dobrze pamiętam, to DbSet<T> implementuje IQueryable sam z siebie i nie ma potrzeby dodawania AsQueryable. Dopóki nie pojawi się cast na jakiś typ IEnumerable to w teorii wszystkie zapytania typu Where czy Select będą konwertowane na SQL - o ile będzie to możliwe. Jeżeli nie da się stworzyć takiego zapytania, to EF powinien rzucić wyjątek
  • Odpowiedz
  • 0
@JanPawelDrugiLechWalesaPierwszy: @drajvver Czyli z warstwy Db spokojnie zwracam IEnurable i tworzę oddzielne metody zależnie co potrzebuje albo pozwalam przesyłać expression do budowania dynamicznie query ? Natomiast jeżeli ktoś pobrał dane z bazy i warstwie biznesu je dalej filtruje to jest to błąd bo można je przefiltrować na bazie.Co szczególnie dotyczy dużej ilości danych.

Czyli podsmarowując AsQurable używamy gdy chcemy query podzielić na wykonywanie na bazie i w aplikacji a
  • Odpowiedz
Czyli z warstwy Db spokojnie zwracam IEnurable i tworzę oddzielne metody zależnie co potrzebuje albo pozwalam przesyłać expression do budowania dynamicznie query


Tak

Natomiast jeżeli ktoś pobrał dane z bazy i warstwie biznesu je dalej filtruje to jest to błąd bo można je przefiltrować na bazie.Co szczególnie dotyczy dużej ilości danych.


Tak,
  • Odpowiedz
@smalczyk1: @drajvver dobrze ci wytłumaczył

Dodam tylko od siebie że gdyby where miałby materializować się po stronie aplikacji to byś musiał ładować cała tabele z bazy danych do pamięci, byłoby to kompletnie bez sensu. Najważniejszy use case IQueryable to dynamiczne budowanie zapytań i do momentu aż nie użyjesz wyżej wspomnianego select czy tolist zapytanie będzie typu IQueryable.
  • Odpowiedz
  • 0
@JanPawelDrugiLechWalesaPierwszy

IQuerable uzywasz zawsze dopóki to jest mozliwe


Co masz na myśli "zawsze". Zwracać z repository nie powinienem IQuerybale bo to antypattern.Natomiast z tego co doczytałem jak clientContext ma ustawione DbSety to one są zawsze IQuerybale .Czy chodziło Ci,żeby nie używać w query AsEnumerable()?
  • Odpowiedz