Diciamo che ho qualcosa chiamato Stuff nel mio database, con una proprietà chiamata Id. Dall'utente ottengo una sequenza di oggetti Range selezionati (o meglio li creo dal loro input) con gli Id che vogliono. Una versione ridotta che struct assomiglia a questo:C#, Linq2SQL: creazione di un predicato per trovare elementi all'interno di un numero di intervalli
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;
}
...
}
Così si potrebbe per esempio hanno ottenuto:
var selectedRange = new List<Range<int>>
{
new Range(1, 4),
new Range(7,11),
};
Allora voglio usarlo per creare un predicato per selezionare solo le cose che hanno un valore tra quelli. Ad esempio, utilizzando il PredicateBuilder, posso per esempio farlo in questo modo:
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);
}
e poi:
var stuff = datacontext.Stuffs.Where(predicate).ToList();
Quale funziona! Quello che vorrei fare ora è creare un metodo di estensione generico per creare quei predicati per me. Un po 'come questo:
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;
}
problema qui, è che si blocca con un NotSupportedException a causa della chiamata di selezione (ø): Method 'System.Object DynamicInvoke(System.Object[])' has no supported translation to SQL.
credo che sia comprensibile. Ma c'è un modo per aggirare questo? Quello che mi piacerebbe finire con è così che ho potuto solo fare:
var stuff = datacontext.Stuffs.Where(selectedRange.ToPredicate<Stuff>(ø => ø.Id));
O, meglio ancora, creare qualcosa che restituisce un IQueryable in modo che ho potuto solo fare:
var stuff = datacontext.Stuffs.WhereWithin<Stuff>(selectedRange, ø => ø.Id); // Possibly without having to specify Stuff as type there...
Così, ogni idee? Mi piace molto per ottenere questo lavoro, perché se non mi metterò un sacco di quei blocchi di codice foreach, creando predicati ...
Nota 1: Certo, sarebbe bello se potessi espandi a più di int, come DateTime e così via, ma non sei sicuro di come finire con l'utilizzo degli operatori> = e < = ... CompareTo funziona con linq-to-sql? Se no, non c'è nessun problema a crearne due. Uno per int e uno per DateTime, dal momento che sono principalmente i tipi per cui sarà usato.
Nota 2: Sarà utilizzato per la segnalazione, in cui l'utente sarà in grado di restringere ciò che viene fuori, in base a cose diverse. Voglio, voglio questo rapporto per quelle persone e quelle date.
Come sarebbe che il lavoro con tutta una serie di Gamma oggetti? –
Svish
Si potrebbe fare lo stesso con OrElse ... io aggiornare ... –
E che cosa è questo "x" nella vostra param? – Svish