2017-09-06 8 views
4

Donc, je suis un peu fatigué de réécrire les mêmes requêtes encore et encore.Extension de IQueryable avec IsInDateTimeRange

repo.Query().Where(stuff => stuff.Timestamp >= minTime && stuff.Timestamp <= maxTime && ...); 

Je pensais que je devrais étendre IQueryable avec une méthode appelée IsInDateTimeRange, et l'utiliser comme ceci

repo.Query().IsInDateTimeRange(stuff => stuff.Timestamp, minTime, maxTime) ... 

ce serait très facile pour IEnumerable, à Func<T, DateTime> et deux DateTime s, mais pour la IQueryable Je dois prendre un Expression et je ne sais pas trop comment l'utiliser.

C'était ma tentative, mais ne semble pas fonctionner.

public static IQueryable<TValue> IsInDateTimeRange<TValue>(
     this IQueryable<TValue> self, 
     Expression<Func<TValue, DateTime>> getMember, 
     DateTime minTime, 
     DateTime maxTime) 
    { 
     return self.Where(value => minTime >= getMember(value) && maxTime <= getMember(value)); 
    } 
+1

Quand vous dites ne fonctionne pas s'il vous plaît expliquer ce que cela signifie. Exception? Erreur de compilation? .. –

+1

La plupart des fournisseurs Linq ne pourraient pas traduire votre expression transformée en une requête de magasin à cause de ce bruit 'getMember (value)'. Vous devrez remplacer manuellement les parties concernées par un accesseur 'Expression.Property'. – haim770

+0

Oui, erreur du compilateur. Impossible d'appeler getMember car ce n'est pas un délégué. – jool

Répondre

7

Vous pouvez accomplir cela en construisant manuellement l'expression basée sur l'expression d'accès à la propriété qui est passé à la méthode:

public static IQueryable<TValue> IsInDateTimeRange<TValue>(
    this IQueryable<TValue> self, 
    Expression<Func<TValue, DateTime>> getMember, 
    DateTime minTime, 
    DateTime maxTime) 
{ 
    var getMemberBody = getMember.Body; 
    var filter = Expression.Lambda<Func<TValue, bool>>(
     Expression.And(
      Expression.LessThanOrEqual(
       Expression.Constant(minTime), 
       getMemberBody 
      ), 
      Expression.LessThanOrEqual(
       getMemberBody, 
       Expression.Constant(maxTime) 
      ) 
     ), 
     getMember.Parameters 
    ); 
    return self.Where(filter); 
} 
+0

Battez-moi. Seul le tweak que je pourrais faire est que vous n'avez pas besoin de prendre 'getMember.Parameters.First()'. Vous devriez pouvoir passer 'getMembers.Parameters' comme second argument de' Lambda <>() '. De plus, le premier 'LessThanOrEqual' devrait être' GreaterThanOrEqual' :). –

+0

@MikeStrobel Vous avez raison, édité pour le faire :) –

+0

Correction de l'erreur de logique mineure pour vous (vous avez utilisé '<=' deux fois). –