97 votes

Quel est le but de AsQueryable()?

Est le but de l' AsQueryable() , de sorte que vous pouvez passer autour d'un IEnumerable pour les méthodes qui pourraient s'attendent IQueryable, ou est-il utile de raison pour représenter IEnumerable comme IQueryable? Par exemple, est-il censé être pour les cas comme cela:

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

Ou faut-il réellement faire quelque chose de différent:

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

Faire l' IQueryable versions de l'extension de ces méthodes que nous venons de construire une Expression qui finit par faire la même chose, une fois exécuté? Ma principale question est, ce qui est un véritable cas d'utilisation pour l'utilisation de AsQueryable?

59voto

Servy Points 93720

Il y a quelques utilisations.

  1. Comme mentionné dans d'autres réponses, vous pouvez l'utiliser pour simuler une source de données interrogeable à l'aide d'une mémoire de la source de données de sorte que vous pouvez facilement tester des méthodes qui pourront éventuellement être utilisés sur un non-énumérable basé IQueryable.

  2. Vous pouvez écrire des méthodes d'assistance pour la manipulation des collections qui peuvent s'appliquer soit en mémoire des séquences ou des sources de données externes. Si vous écrivez votre aide, les méthodes à utiliser en IQueryable entièrement, vous pouvez utiliser AsQueryable sur tous les enumerables à les utiliser. Cela vous permet d'éviter d'écrire deux versions distinctes de très généralisée des méthodes d'assistance.

  3. Il vous permet de modifier le temps de compilation type de interrogeable à un IQueryable, plutôt qu'à une plus type dérivé. En effet, vous feriez l'utiliser sur un IQueryable à la même heure que vous souhaitez utiliser AsEnumerable sur IEnumerable. Vous pourriez avoir un objet qui implémente IQueryable mais qui dispose également d'une instance Select méthode. Si c'était le cas, et que vous vouliez utiliser LINQ Select méthode, vous aurez besoin de changer le moment de la compilation, le type de l'objet d' IQueryable. Vous pouvez simplement le jeter, mais en ayant un AsQueryable méthode, vous pouvez profiter de l'inférence de type. Ce n'est tout simplement plus pratique si le générique de la liste d'arguments est complexe, et il est effectivement nécessaire si l'un des arguments génériques sont les types anonymes.

12voto

chris Points 41

La plupart des cas valide que j'ai pour AsQueryable est des tests unitaires. Dire que j'ai la suite un peu artificiel exemple

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

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


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

et je veux écrire un test unitaire pour assurez-vous que le contrôleur repasse les résultats retournés par le référentiel. Ce serait ressembler à quelque chose comme ceci:

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

où vraiment, tous les AsQueryable() la méthode me permet de le faire est de satisfaire le compilateur lors de la configuration d'une fantaisie.

Je serais intéressé lorsqu'il est utilisé dans le code de l'application.

10voto

Scott Points 162

Comme sanjuro a noté, dans le but de AsQueryable() est expliqué dans l'Aide de AsQueryable Avec Linq to Objects Et Linq to SQL. En particulier, l'article stipule,

Cette offre d'excellentes prestations dans la vraie parole des scénarios où vous avez certaines méthodes sur une entité qui retourne un IQueryable de T et de certaines méthodes de retour de la Liste. Mais alors, vous avez des affaires de la règle de filtre qui doit être appliqué sur l'ensemble de la collection, peu importe si la collection est retourné comme IQueryable de T ou IEnumerable de T. à Partir d'une performance, vous voulez vraiment tirer parti de l'exécution du filtre d'entreprise sur la base de données si la collection met en œuvre IQueryable tombent à l'arrière pour appliquer le filtre dans la mémoire à l'aide de Linq pour objet la mise en œuvre des délégués.

5voto

sanjuro Points 474

Le but de AsQueryable() est largement expliqué dans cet article à l'Aide de AsQueryable Avec Linq to Objects Et Linq to SQL

Des commentaires de l'article de MSDN Interrogeable.AsQueryable Méthode:

Si le type de la source met en œuvre IQueryable, AsQueryable(IEnumerable) renvoie directement. Sinon, elle renvoie un IQueryable qui exécute les requêtes en appel de la requête équivalente opérateur méthodes de Énumérable au lieu de celles de Interrogeable.

C'est exactement ce qui est mentionné et utilisé dans l'article ci-dessus. Dans votre exemple, il dépend de ce qui est orderRepo.GetAll retour, IEnumerable IQueryable(Linq to Sql). Si elle renvoie IQueryable, la méthode Count() sera exécutée sur la base de données, autrement, il sera exécuté dans la mémoire. Regardez attentivement exemple dans l'article référencé.

3voto

Tigran Points 41381

Interface IQueryable citant le de la documentation:

Le IQueryable interface est prévu pour la mise en œuvre par requête les prestataires.

Donc, pour quelqu'un qui a l'intention de faire ses datastracture queryable .NET, qui discbased que pas nécessaire, d'être énuméré ou la validité de l'agent recenseur.

IEnumerator est une interface pour l'itération et le traitement des flux de données à la place.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X