Jaki jest cel AsQueryable ()?

Jest celem AsQueryable() tylko po to, aby można było przekazać IEnumerable metodom, które mogą się spodziewać IQueryable, czy jest jakiś użyteczny powód, aby reprezentować IEnumerable jako IQueryable? Na przykład, czy ma to być dla takich przypadków:

IEnumerable<Order> orders = orderRepo.GetAll();

// I don't want to create another method that works on IEnumerable,
// so I convert it here.
CountOrders(orders.AsQueryable());

public static int CountOrders(IQueryable<Order> ordersQuery)
{
    return ordersQuery.Count();
}

A może faktycznie sprawia, że robi coś innego:

IEnumerable<Order> orders = orderRepo.GetAll();
IQueryable<Order> ordersQuery = orders.AsQueryable();

IEnumerable<Order> filteredOrders = orders.Where(o => o.CustomerId == 3);
IQueryable<Order> filteredOrdersQuery = ordersQuery.Where(o => o.CustomerId == 3);

// Are these executed in a different way?
int result1 = filteredOrders.Count();
int result2 = filteredOrdersQuery.Count();

Czy wersje tych metod rozszerzeń po prostu budują wyrażenie, które robi to samo po wykonaniu? Moje główne pytanie brzmi, co to jest prawdziwy przypadek użycia AsQueryable?

Author: Soner Gönül, 2013-06-28

5 answers

Istnieje kilka głównych zastosowań.

  1. Jak wspomniano w innych odpowiedziach, można go użyć do wyśmiewania źródła danych z zapytań za pomocą źródła danych w pamięci, dzięki czemu można łatwiej testować metody, które ostatecznie zostaną użyte na bazie nieujemnej IQueryable.

  2. Można pisać metody pomocnicze do manipulowania kolekcjami, które mogą być stosowane do sekwencji w pamięci lub zewnętrznych źródeł danych. Jeśli piszesz swoje metody pomocy do wykorzystania IQueryable w całości możesz po prostu użyć AsQueryable na wszystkich enumerable, aby ich używać. Pozwala to uniknąć pisania dwóch oddzielnych wersji bardzo uogólnionych metod pomocniczych.

  3. Pozwala zmienić typ czasu kompilacji zapytania na IQueryable, a nie na typ Pochodny. W efekcie; użyłbyś go na IQueryable w tym samym czasie, w którym użyłbyś AsEnumerable na IEnumerable. Możesz mieć obiekt implementujący metodę IQueryable, ale również instancję metody Select. Gdyby tak było, a chcielibyście skorzystać z Metoda LINQ Select, trzeba by zmienić typ czasu kompilacji obiektu na IQueryable. Możesz go po prostu rzucić, ale mając metodę AsQueryable możesz skorzystać z wnioskowania typu. Jest to po prostu wygodniejsze, jeśli ogólna lista argumentów jest złożona i jest to w rzeczywistości konieczne , jeśli którykolwiek z ogólnych argumentów jest anonimowym typem.

 48
Author: Servy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-04 15:24:54

Najodpowiedniejszy przypadek jaki mam dla AsQueryable to testy jednostkowe. Powiedzmy, że mam następujący nieco wymyślony przykład

public interface IWidgetRepository
{
   IQueryable<Widget> Retrieve();
} 

public class WidgetController
{
   public IWidgetRepository WidgetRepository {get; set;}


   public IQueryable<Widget> Get()
   {
      return WidgetRepository.Retrieve();
   }
}

I chcę napisać test jednostkowy, aby upewnić się, że kontroler przekazuje wyniki zwrócone z repozytorium. Wyglądałoby to mniej więcej tak:

[TestMethod]
public void VerifyRepositoryOutputIsReturned()
{    
    var widget1 = new Widget();
    var widget2 = new Widget();
    var listOfWidgets = new List<Widget>() {widget1, widget2};
    var widgetRepository = new Mock<IWidgetRepository>();
    widgetRepository.Setup(r => r.Retrieve())
      .Returns(listOfWidgets.AsQueryable());
    var controller = new WidgetController();
    controller.WidgetRepository = widgetRepository.Object;

    var results = controller.Get();

    Assert.AreEqual(2, results.Count());
    Assert.IsTrue(results.Contains(widget1));
    Assert.IsTrue(results.Contains(widget2));
}

Gdzie tak naprawdę, cała Metoda AsQueryable() pozwala mi zrobić to zadowolić kompilator podczas konfigurowania makiety.

Byłbym ciekaw, gdzie jest to używane w kodzie aplikacji.

 10
Author: chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-04 12:45:28

Jak zauważył sanjuro, cel asqueryable() jest wyjaśniony w używając AsQueryable z Linq do obiektów i Linq do SQL. W szczególności artykuł stwierdza,

To oferuje doskonałe korzyści w rzeczywistych scenariuszach word, gdzie masz pewne metody na encji, które zwracają IQueryable z T i niektóre metody zwracają listę. Ale wtedy masz filtr reguł biznesowych, który musi być zastosowany na całej kolekcji, niezależnie od tego, czy kolekcja jest zwracana jako IQueryable z t lub IEnumerable T. Z punktu widzenia wydajności, naprawdę chcesz wykorzystać wykonywanie filtra biznesowego w bazie danych, jeśli kolekcja implementuje IQueryable, w przeciwnym razie wróć do zastosowania filtra biznesowego w pamięci za pomocą Linq do obiektowej implementacji delegatów.

 8
Author: Scott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-04 23:38:43

Interfejs IQueryable cytowanie dokumentacji:

Interfejs IQueryable jest przeznaczony do implementacji poprzez zapytanie dostawcy.

Więc dla kogoś, kto zamierza zrobić swoje datastracture queryable w. NET, że datastruktura , które nie są konieczne, może być wyliczona lub mieć ważny enumerator .

IEnumerator jest interfejsem do iteracji i przetwarzania strumienia danych.

 2
Author: Tigran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-28 14:27:20

Cel asqueryable() jest znacznie wyjaśniony w tym artykule Używanie AsQueryable z Linq to Objects i Linq To SQL

Z sekcji Uwagi MSDN Queryable.Metoda AsQueryable:

Jeśli typ źródła implementuje IQueryable, AsQueryable (IEnumerable) zwraca go bezpośrednio. W przeciwnym razie zwraca IQueryable, który wykonuje zapytania, wywołując równoważne metody operatora zapytań w Enumerable zamiast tych w Queryable.

To jest dokładnie to, co jest wspomniane i użyte w powyższym artykule. W twoim przykładzie, to zależy od tego, co jest orderRepo.GetAll returning, IEnumerable lub IQueryable (Linq to Sql). Jeśli zwróci IQueryable, metoda Count() zostanie wykonana w bazie danych, w przeciwnym razie zostanie wykonana w pamięci. Przyjrzyj się uważnie przykładowi w cytowanym artykule.

 2
Author: sanjuro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-04 15:13:49