Linq: laisser la déclaration comme une constante?

.net c# entity-framework-6 expression-trees linq

Question

Je travaille sur une instruction d'expression de requête Linq et souhaite utiliser une instruction let pour définir une valeur constante dans le cadre de la requête afin de réduire les erreurs potentielles.

Dans mon exemple ... (c'est la maquette totale). l'instruction let "validateCount" est la question.

    from referenceRow in context.SomeTable
    // We want 8 in the Take and the results to still be 8 after the where. 
    // instead of typing in the value twice (in this example), i wanted to use a constant value here
    let validateCount = 8

    // sub query expression in my example
    let subQuery = from sub in context.SomeTable
               where sub.SomeColumn == rowReference.SomeColumn
               orderby sub.SomeColumn descending
               select sub

// use the sub query, take X amount, apply filter, check to see if Count() is the same as Take()
where subQuery.Take(validateCount) // this is where we fail. if we put in the constant 8, we are ok.
              .Where(x => x.SomeOtherColumn == "Some value")
              .Count() == validateCount // this is fine
select referenceRow

Malheureusement, il semble que l'expression let "validateCount", qui a une valeur unique de 8 dans cet exemple, ne puisse fonctionner que dans la partie comparaison de .Count () mais ne puisse être transmise à .Take () sans lever d'exception.

La limite doit être une expression DbConstantExpression ou DbParameterReferenceExpression. Nom du paramètre: count

À la recherche d'une solution pour utiliser une constante définie par l'utilisateur dans un emplacement de code unique pouvant être utilisé dans le reste de l'expression de la requête, à la fois dans .Take () et .Count () sans avoir à mettre à jour plusieurs zones du code .

Notre application permet aux utilisateurs de fournir leur propre expression de requête linq pour construire leurs requêtes. Je ne peux pas définir quoi que ce soit en dehors du champ de cette requête, et je dois y être, en utilisant quelque chose comme une instruction 'let'.

Réponse acceptée

let instruction let génère une projection de type anonyme intermédiaire (appel de Select ) dans l'arborescence d'expression de la requête. Le fournisseur de requêtes EF (comme indiqué par le message d'exception) exige que les arguments Skip et Take soient résolus en valeurs constantes ou variables (c'est-à-dire pour pouvoir être évalués localement). Par conséquent, la let ne peut pas être utilisée à cette fin.

Au lieu de cela, les constantes / variables utilisées dans les expressions Skip / Take doivent être définies en dehors de la requête et utilisées à l'intérieur.

Pour définir une valeur constante, vous utiliseriez:

const int validateCount = 8;
var query = (from .... Take(validateCount) ...);

Pour définir une valeur de variable (paramètre de requête SQL):

int validateCount = 8;
var query = (from .... Take(validateCount) ...);

Ici, le compilateur C # transformera validateCount en fermeture et le fournisseur de requêtes EF sera heureux de lier un paramètre (avec cette valeur).

Notre application permet aux utilisateurs de fournir leur propre expression de requête linq pour construire leurs requêtes. Je ne peux pas définir quoi que ce soit en dehors du champ de cette requête, et je dois y être, en utilisant quelque chose comme une instruction 'let'.

Lorsqu'ils fournissent leurs propres requêtes, les utilisateurs doivent suivre les mêmes règles d'argument Skip / Take que ci-dessus, c'est-à-dire définir leurs constantes et leurs variables en dehors de leurs requêtes.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow