2017-09-06 5 views
4

So bin ich etwas müde von immer wieder die gleichen Abfragen umschreiben.Erweitern IQueryable mit IsInDateTimeRange

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

Ich dachte, ich IQueryable mit einem Verfahren IsInDateTimeRange erweitern sollte aufgerufen, und es verwenden, wie diese

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

dies für IEnumerable sehr einfach wäre, nur Func<T, DateTime> und zwei DateTime s, jedoch für die IQueryable Ich muss ein Expression nehmen und ich bin nicht wirklich sicher, wie man das benutzt.

Das war mein Versuch, aber scheint nicht zu funktionieren.

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

Wenn Sie nicht sagen, arbeiten Sie bitte erklären, was es bedeutet. Ausnahme? Kompilierfehler? .. –

+1

Die meisten Linq-Provider konnten Ihren transformierten Ausdruck aufgrund dieses 'getMember (value)' noise nicht in eine Speicherabfrage übersetzen. Sie müssen die relevanten Teile manuell durch einen regulären "Expression.Property" -Accessor ersetzen. – haim770

+0

Ja, Compilerfehler. getMember kann nicht aufgerufen werden, da es sich nicht um einen Delegaten handelt. – jool

Antwort

7

Sie können dies erreichen, indem manuell den Ausdruck Gebäude auf dem Grundstück Zugriff Ausdruck basiert, die an die Methode übergeben wird:

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

Beat mich dazu. Nur zwicken, was ich machen könnte, ist, dass du 'getMember.Parameters.First()' nicht wirklich nehmen musst. Sie sollten 'getMembers.Parameters' als zweites Argument für' Lambda <>() 'übergeben können. Außerdem sollte der erste 'LessThanOrEqual'' GreaterThanOrEqual' sein :). –

+0

@MikeStrobel Du hast Recht, bearbeitet, um es so zu machen :) –

+0

für Sie die kleinere Logikfehler behoben (Sie verwendet '<=' zweimal). –