Disons que j'ai quelque chose appelé Stuff dans ma base de données, avec une propriété appelée Id. De l'utilisateur, je reçois une séquence d'objets Range sélectionnés (ou plutôt je les crée à partir de leur entrée) avec les Ids qu'ils veulent. Une version dépouillée de cette struct ressemble à ceci:C#, Linq2SQL: Création d'un prédicat pour trouver des éléments dans un certain nombre de plages
public struct Range<T> : IEquatable<Range<T>>, IEqualityComparer<Range<T>>
{
public T A;
public T B;
public Range(T a, T b)
{
A = a;
B = b;
}
...
}
Donc, on pourrait par exemple avoir obtenu:
var selectedRange = new List<Range<int>>
{
new Range(1, 4),
new Range(7,11),
};
Je veux ensuite l'utiliser pour créer un prédicat de sélectionner uniquement les choses qui ont un valeur entre ceux-ci. Par exemple, en utilisant le PredicateBuilder, je peux par exemple faire de cette façon:
var predicate = PredicateBuilder.False<Stuff>();
foreach (Range<int> r in selectedRange)
{
int a = r.A;
int b = r.B;
predicate = predicate.Or(ø => ø.Id >= a && ø.Id <= b);
}
puis:
var stuff = datacontext.Stuffs.Where(predicate).ToList();
Ce qui fonctionne! Ce que je voudrais faire maintenant, est de créer une méthode d'extension générique pour créer ces prédicats pour moi. Un peu comme ceci:
public static Expression<Func<T,bool>> ToPredicate<T>(this IEnumerable<Range<int>> range, Func<T, int> selector)
{
Expression<Func<T, bool>> p = PredicateBuilder.False<T>();
foreach (Range<int> r in range)
{
int a = r.A;
int b = r.B;
p = p.Or(ø => selector(ø) >= a && selector(ø) <= b);
}
return p;
}
problème ici, est qu'il tombe en panne avec un NotSupportedException en raison du sélecteur (ø) Appel: Method 'System.Object DynamicInvoke(System.Object[])' has no supported translation to SQL.
Je suppose que c'est compréhensible. Mais y a-t-il un moyen de contourner cela? Ce que je voudrais retrouver avec pour que je pouvais faire:
var stuff = datacontext.Stuffs.Where(selectedRange.ToPredicate<Stuff>(ø => ø.Id));
Ou mieux encore, créer quelque chose qui retourne un IQueryable pour que je pouvais faire:
var stuff = datacontext.Stuffs.WhereWithin<Stuff>(selectedRange, ø => ø.Id); // Possibly without having to specify Stuff as type there...
Ainsi, tout des idées? Je voudrais vraiment obtenir ce travail, parce que si je ne vais obtenir beaucoup de ces blocs foreach de code, la création prédicats ...
Note 1: Bien sûr, serait bien si je pouvais expand à plus de int, comme DateTime et autres, mais je ne sais pas comment cela finit par utiliser les opérateurs 0 = = < = ... Est-ce que CompareTo fonctionne avec linq-to-sql? Sinon, il n'y a pas de problème à en créer deux. Un pour int et un pour DateTime, puisque ce sont principalement les types pour lesquels cela sera utilisé.
Note 2: Il sera utilisé pour les rapports, où l'utilisateur sera en mesure d'affiner ce qui sort, en fonction de choses différentes. Comme, je veux ce rapport pour ces personnes et ces dates.
Comment cela fonctionnerait-il avec toute une série d'objets Range? –
Svish
Vous pourriez faire la même chose avec OrElse ... Je vais mettre à jour ... –
Et quel est ce "x" dans votre param? – Svish