8
votes

Comment maintenir l'exécution différée LINQ?

Supposons que j'ai une expression iquéryable que j'aimerais encapsuler la définition de, stocker et la réutiliser ou l'intégrer dans une requête plus grande plus tard. Par exemple: XXX

Maintenant, je crois que je peux simplement garder cet objet MyQuery autour et l'utiliser comme je l'ai décrit. Mais certaines choses que je ne suis pas sûre de:

  1. Comment le permet de paramétrer le mieux? Initialement, j'ai défini ceci dans une méthode, puis renvoyé le iquéryable à la suite de la méthode. De cette façon, je peux définir bla et bar comme des arguments de la méthode et je suppose que cela crée simplement un nouveau iquéryable à chaque fois. Est-ce le meilleur moyen d'encapsuler la logique d'un iquéryable ? Y a-t-il d'autres moyens?

  2. Et si ma requête se résout à un scalaire plutôt que iquéryable ? Par exemple, que si je veux que cette requête soit exactement comme indiqué, comme indiqué comme indiqué mais qu'appendez . Nan () Pour simplement me faire savoir s'il y avait des résultats correspondants? Si j'ajoute le (...). Tout () alors le résultat est bool et immédiatement exécuté, non? Existe-t-il un moyen d'utiliser ces opérateurs ( tout , sindleordfault , etc.) sans exécuter immédiatement? Comment Linq-to-SQL gérer cela?

    EDIT: La partie 2 est vraiment plus sur l'essai de comprendre quelles sont les différences de limitation entre iquérirable .where (expression > ) vs. iquéryable . Nany (expression >) . Il semble que ce dernier ne soit pas aussi flexible lors de la création de requêtes plus importantes lorsque l'exécution doit être retardée. Le où () peut être ajouté et ensuite d'autres constructions peuvent être ensuite ajoutées et ensuite exécutées. Depuis que le tout () renvoie une valeur scalaire à laquelle on sonne comme il s'exécutent immédiatement avant que le reste de la requête puisse être construit.


0 commentaires

4 Réponses :


5
votes
  1. Vous devez être vraiment prudent de passer autour de IQuéryables lorsque vous utilisez un DataContext, car une fois que le contexte est disposé, vous ne pourrez plus exécuter sur ce iQuiserable. Si vous n'utilisez pas de contexte, vous serez peut-être bien, mais soyez conscient de cela.

  2. . Nan () et .Firstordefault () sont non différés. Lorsque vous les appelez, ils seront l'exécution de cause. Cependant, cela peut ne pas faire ce que vous pensez. Par exemple, à Linq à SQL si vous exécutez un. Nany () sur un iquérissable, il agit comme un si existez (SQL ici) fondamentalement.

    Vous pouvez chaîner la chaîne iQueryable de comme ceci si vous voulez: xxx


3 commentaires

On dirait que dans le n ° 1, ayant une méthode qui construit essentiellement un nouveau iquéryable à chaque fois est une bonne chose De cette façon je ne rencontrerai pas de problèmes avec une disposition. Dans N ° 2, je suis confondre à la manière dont LINQ-TO-SQL peut traduire le n'importe quel opérateur , mais je ne peux pas différer. Si je devais utiliser un n'importe quel opérateur dans une requête plus grande est-il immédiatement exécuté là aussi, ou fait-il partie de la plus grande exécution de la requête?


Ok je pense que je suis presque là. Si je devais incorporer un . Nan () dans un où la clause , il ne l'exécuterait pas dans une boucle, correct? Cela compilerait à l'expression SQL appropriée et à renvoyer cela. Donc, en effet, ce n'est pas . Nan () qui empêche l'exécution différée car c'est la manière dont elle est utilisée. Fondamentalement, si le résultat d'une requête totale est un scalaire, les chiffres du compilateur que vous avez besoin du résultat sont maintenant plutôt que de continuer à construire un iquéryable .


@MCKamey correct, dès que vous utilisez. Nany () dans un contexte qui n'est pas différé, il sera exécuté. Dans le cas de .Où (), il cherche une expression, qui est différée, alors tu vas bien. Dans le cas de Var ou de la boucle de Foreach, ceux-ci provoquent une exécution parce qu'ils ne sont pas différables.



2
votes

Une bien meilleure option que la mise en cache des objets iquérissables consiste à cacher des arbres d'expression. Tous les objets iquérissables ont une propriété appelée expression (je crois), qui représente l'arbre d'expression actuel pour cette requête.

À un moment ultérieur à temps, vous pouvez recréer la requête en appelant requéryable.Provider.creequace (expression) ou directement sur tout ce que le fournisseur est (dans votre cas, un contexte de données LINQ2SQL).

Paramétrage Ces arbres d'expression sont légèrement plus difficiles, car ils utilisent des exressions constantes pour créer une valeur. Afin de paramétrer ces requêtes, vous devrez reconstruire la requête à chaque fois que vous souhaitez différents paramètres.


2 commentaires

Je dirais que le paramétrage (ou plus important encore une unité de logique unique) est le véritable objectif ici plutôt que de la mise en cache. Considérant que le compilateur C # a déjà convertit, je ne pense pas qu'un équivalent d'exécution serait de beaucoup d'avantages d'utilisation / de performance (comme cela implique la mise en cache).


Pouvez-vous expliquer pourquoi cette option est meilleure? Pour autant que je comprenne, vous venez de déballer l'expression pour le réarranger ultérieurement: pourquoi ne pas garder l'emballage tel quel?



2
votes

tout () code> utilisé de cette manière est différé. xxx pré>

tout () code> utilisé de cette manière n'est pas différé, mais est toujours Traduit en SQL (la table des clients entière n'est pas chargée en mémoire). P>

Func<bool> f = dc.Customers.DeferredAny();
bool result = f();


4 commentaires

Lorsque vous dites différé, cela vous semble que vous voulez dire que je peux définir une expression de Lambda (ou déléguer) mais pas l'exécuter immédiatement. Je pense qu'il existe une subtilité du concept de Linq d'une "exécution différée" qui permet à l'opération de faire partie d'un arbre d'expression plus vaste, qui peut être interprété par le fournisseur, mais il veut. Ma question est plus tente d'essayer de passer à quelles sont les différences de limitation entre iquérirable .where (expression >) vs. code> iqueriserable . Expression >) Comme il semble que ce dernier n'était pas aussi flexible.


Cette inflexibilité vient de la différence de types de retour. Le type nommé 'bool' ne peut avoir aucun comportement différé.


Cette suggestion me semble trop pauvre (considérez le DataContext)


@Cottsak - Toutes les méthodes d'extension (y compris celles pour Linq) sont statiques, telles que msdn.microsoft.com/en-us/library/bb535040.aspx . Les méthodes statiques sont threadsafe tant qu'il n'y a pas d'état statique (tel qu'une propriété statique ou un champ).



0
votes

Créer une application partielle de votre requête à l'intérieur d'une expression xxx

et vous pouvez ensuite l'utiliser par ... xxx

le La requête pourrait être encapsulée dans une classe si vous souhaitez le rendre plus portable / réutilisable. xxx


0 commentaires