Middle
Czym jest IQueryable w kontekście C#?
sobes.tech AI
Odpowiedź od AI
IQueryable<T> jest interfejsem w LINQ, który umożliwia tworzenie i wykonywanie zapytań do źródła danych obsługującego opóźnioną ocenę i możliwość tworzenia drzewa wyrażeń.
Kluczowe cechy:
- Opóźniona ocena: Zapytanie nie jest wykonywane od razu podczas tworzenia, lecz tylko wtedy, gdy konieczne jest uzyskanie wyników (np. podczas iteracji po kolekcji lub wywołania
ToList(),ToArray()). - Drzewo wyrażeń: Zapytanie jest reprezentowane w formie drzewa wyrażeń (
Expression<Func<T>>), które może być analizowane i przekształcane w coś zrozumiałego dla źródła danych (np. zapytanie SQL dla bazy danych). - Filtrowanie i projekcja po stronie źródła danych: Dzięki drzewu wyrażeń operacje filtrowania (
Where), sortowania (OrderBy) i projekcji (Select) mogą być wykonywane po stronie źródła danych, co znacznie zwiększa wydajność, szczególnie przy pracy z dużymi ilościami danych.
Różnice w stosunku do IEnumerable<T>:
| Cecha | IEnumerable<T> |
IQueryable<T> |
|---|---|---|
| Ocena | Natychmiastowa/odroczona (zależy od źródła) | Opóźniona |
| Pobieranie danych | Cała kolekcja może być załadowana do pamięci | Ładowane są tylko potrzebne dane po wykonaniu |
| Gdzie wykonywana jest filtracja/projekcja | W pamięci aplikacji | Po stronie źródła danych |
| Podstawa | Kolekcje w pamięci, tablice | Źródła danych (bazy danych, serwisy internetowe itp.) |
| Obsługa wyrażeń | Nie (używa delegatów Func<T>) |
Tak (używa drzew wyrażeń Expression<Func<T>>) |
Przykład użycia:
using System.Linq;
using System.Collections.Generic;
// Załóżmy, że to jest źródło danych obsługujące IQueryable
public class DataSource
{
private List<Person> people = new List<Person>
{
new Person { Name = "Alice", Age = 30 },
new Person { Name = "Bob", Age = 25 },
new Person { Name = "Charlie", Age = 35 }
};
public IQueryable<Person> GetPeople()
{
// W rzeczywistej sytuacji byłoby to zapytanie do bazy danych lub innego źródła
return people.AsQueryable();
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
// Użycie
public class Program
{
public static void Main(string[] args)
{
DataSource dataSource = new DataSource();
// Tworzenie zapytania z IQueryable - zapytanie jeszcze nie jest wykonane
IQueryable<Person> query = dataSource.GetPeople()
.Where(p => p.Age > 28)
.OrderBy(p => p.Name);
// Wykonanie zapytania podczas iteracji
foreach (var person in query)
{
Console.WriteLine($"{person.Name}, {person.Age}");
}
// Wykonanie zapytania podczas konwersji do listy
List<Person> seniors = query.ToList();
}
}