it-swarm.com.de

Was ist der Zweck von AsQueryable ()?

Ist der Zweck von AsQueryable() nur, damit Sie ein IEnumerable an Methoden übergeben können, die IQueryable erwarten könnten, oder gibt es einen nützlichen Grund, IEnumerable darzustellen? als IQueryable? Zum Beispiel soll es für Fälle wie diesen sein:

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();
}

Oder macht es tatsächlich etwas anderes:

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();

Bauen die IQueryable -Versionen dieser Erweiterungsmethoden nur einen Ausdruck auf, der nach seiner Ausführung dasselbe tut? Meine Hauptfrage ist, was ist ein echter Anwendungsfall für die Verwendung von AsQueryable?

90
Ocelot20

Es gibt einige Hauptanwendungen.

  1. Wie in anderen Antworten erwähnt, können Sie damit eine abfragbare Datenquelle mithilfe einer speicherinternen Datenquelle verspotten, sodass Sie Methoden, die möglicherweise auf einer nicht aufzählbaren Basis von IQueryable verwendet werden, einfacher testen können.

  2. Sie können Hilfsmethoden für die Bearbeitung von Sammlungen schreiben, die entweder für speicherinterne Sequenzen oder für externe Datenquellen gelten können. Wenn Sie Ihre Hilfemethoden so schreiben, dass sie IQueryable vollständig verwenden, können Sie AsQueryable für alle Enumerables verwenden, um sie zu verwenden. Auf diese Weise können Sie vermeiden, zwei separate Versionen von sehr verallgemeinerten Hilfsmethoden zu schreiben.

  3. Sie können den Kompilierungszeittyp eines abfragbaren Elements so ändern, dass er ein IQueryable und nicht ein abgeleiteter Typ ist. In der Wirkung; Sie würden es auf einem IQueryable zur selben Zeit verwenden, zu der Sie AsEnumerable auf einem IEnumerable verwenden würden. Möglicherweise haben Sie ein Objekt, das IQueryable implementiert, das jedoch auch eine Instanzmethode Select enthält. Wenn dies der Fall wäre und Sie die Methode LINQ Select verwenden möchten, müssen Sie den Typ der Kompilierungszeit des Objekts in IQueryable ändern. Sie könnten es einfach umwandeln, aber mit einer AsQueryable -Methode können Sie die Typinferenz nutzen. Dies ist einfach praktischer, wenn die Liste der generischen Argumente komplex ist und es tatsächlich erforderlich ist, wenn eines der generischen Argumente ein anonymer Typ ist.

56
Servy

Der beste Fall, den ich für AsQueryable habe, ist das Testen von Einheiten. Angenommen, ich habe das folgende etwas erfundene Beispiel

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

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


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

und ich möchte einen Komponententest schreiben, um sicherzustellen, dass der Controller die vom Repository zurückgegebenen Ergebnisse zurückgibt. Es würde ungefähr so ​​aussehen:

[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));
}

wobei wirklich alles, was ich mit der AsQueryable () -Methode machen kann, ist, den Compiler beim Einrichten eines Mocks zufrieden zu stellen.

Mich würde interessieren, wo dies im Anwendungscode verwendet wird.

10
chris

Wie bereits erwähnt, wird der Zweck von AsQueryable () in Verwenden von AsQueryable mit Linq To-Objekten und Linq To SQL erläutert. Insbesondere heißt es in dem Artikel:

Dies bietet hervorragende Vorteile in realen Word-Szenarien, in denen Sie bestimmte Methoden für eine Entität haben, die ein IQueryable von T zurückgeben, und einige Methoden eine Rückgabeliste. Dann haben Sie jedoch einen Geschäftsregelfilter, der auf die gesamte Auflistung angewendet werden muss, unabhängig davon, ob die Auflistung als IQueryable von T oder IEnumerable von T zurückgegeben wird. Unter Performance-Gesichtspunkten möchten Sie die Ausführung des Geschäftsfilters in der Datenbank wirklich nutzen, wenn Die Auflistung implementiert IQueryable, andernfalls wird auf den Geschäftsfilter im Speicher zurückgegriffen, indem Linq verwendet wird, um die Implementierung von Delegaten zu objektieren.

8
Scott

Der Zweck von AsQueryable () wird in diesem Artikel ausführlich erläutert Verwenden von AsQueryable mit Linq To-Objekten und Linq To SQL

Aus dem Abschnitt "Bemerkungen" der MSDN-Methode "Queryable.AsQueryable":

Wenn der Quelltyp IQueryable implementiert, gibt AsQueryable (IEnumerable) ihn direkt zurück. Andernfalls wird ein IQueryable zurückgegeben, das Abfragen durch Aufrufen der entsprechenden Abfrageoperatormethoden in Enumerable anstelle der in Queryable ausführt.

Das ist genau das, was im obigen Artikel erwähnt und verwendet wird. In Ihrem Beispiel hängt es davon ab, was orderRepo.GetAll zurückgibt, IEnumerable oder IQueryable (Linq to Sql). Wenn IQueryable zurückgegeben wird, wird die Count () -Methode in der Datenbank ausgeführt, andernfalls wird sie im Speicher ausgeführt. Schauen Sie sich das Beispiel in dem Artikel, auf den verwiesen wird, genau an.

3
sanjuro

Schnittstelle IQueryable zitiert Dokumentation:

Die IQueryable-Schnittstelle ist für die Implementierung durch Abfrageanbieter vorgesehen.

Also für jemanden, der beabsichtigt, seine Datenstruktur in .NET abfragbar zu machen, diese Datenstruktur die nicht erforderlich ist, kann aufgezählt werden oder einen gültigen Enumerator haben.

IEnumerator ist eine Schnittstelle zum Iterieren und Verarbeiten Datenstrom.

2
Tigran