3

Ich habe 2 Entity Framework-Abfragen, die fast identisch sind außer der Lambda für 2 Eigenschaften; Ort und DateTime in der Select() Methode.Ist es möglich, ein Lambda in Linq zu Entities zu parametrieren, wählen Sie

Ich habe versucht, eine Erweiterungsmethode zu schaffen, die wählen zu teilen, die ohne die func param funktioniert, aber das löst eine Ausnahme dann verwende ich den Standort param:

public static IQueryable<DashboardItem> SelectDashboardItem(this IQueryable<Job> query, 
      string direction, 
      Func<Job, MeetingDetail> location) 
    { 
     return query 
      .Select(j => new DashboardItem() 
      { 
       JobId = j.Id, 
       Direction = direction, 
       CustomerName = j.Driver.Name, 
       Vehicle = j.Vehicle, 
       // This works without using the func 
       Location = location(j).MeetingLocation.Name, 
       DateTime = location(j).DateTime,      
      }); 
    } 

ich seine Fehlermeldung:

Der LINQ-Ausdrucksknotentyp 'Invoke' wird in LINQ to Entities nicht unterstützt.

Antwort

1

Verwenden Sie diese Syntax mit der Anweisung let, um die Komposition auf einen Schlag zu erstellen. Sie benötigen eine Basisklasse oder besser eine Schnittstelle für die Gemeinsamkeiten zwischen den Entitäten für den Abgang und die Rückkehr.

var query = from job in _dataContext.Job 
    let departureOrReturn = (direction == "PickUp" ? job.Departure : job.Return) as BaseReturnOrDeparture 
    where (departureOrReturn.DateTime >= startDate && departureOrReturn.DateTime <= endDate) 
    select new DispatchDashboardItem 
    { 
     JobId = job.Id, 
     Direction = direction, 
     CustomerName = job.Driver.Name, 
     Vehicle = job.Vehicle, 
     Location = deptartureOrReturn.MeetingLocation.Name, 
     DateTime = deptartureOrReturn.DateTime, 
    }; 
+1

benutzt Sorry vielleicht hat meine lange Frage Verwirrung verursacht, ist in der .Select-Methode, ' Location 'und' DateTime', die abhängig von der Richtung entweder 'j.Return' oder' j.Departure' verwenden müssen. Daher versuche ich, sie auf eine Erweiterungsmethode zu verschieben. –

+0

Überprüfen Sie die letzte Bearbeitung und die zweite Syntax 't haben einen Compiler praktisch, aber so etwas ist eine einfachere Möglichkeit, dies zu erreichen. –

+0

Warum ist das downvoted? –

0

Statt Verwendung Func als Parameter ein Expression .pass die gleiche Lambda-Ausdruck, den Sie als Parameter verwenden verwenden, wird es implizit konvertiert. Nun zu erreichen, was Sie brauchen, müssen Sie LinqKit Bibliothek verwenden:

public static IQueryable<DashboardItem> SelectDashboardItem(this IQueryable<Job> query, 
      string direction, 
      Expression<Func<Job, MeetingDetail>> location) 
    { 
     return query.AsExpandable() 
     .Select(j => new DashboardItem() 
     { 
      JobId = j.Id, 
      Direction = direction, 
      CustomerName = j.Driver.Name, 
      Vehicle = j.Vehicle, 
      // This works without using the func 
      Location = location.Invoke(j).MeetingLocation.Name, 
      DateTime = location.Invoke(j).DateTime,      
     }); 
    } 

Explanation:

ToExpandable schafft eine dünne Hülle um das DLINQ Table-Objekt. Dank dieses Wrappers können Sie die zweite Methode namens Invoke verwenden, die die Expression-Klasse erweitert, um den Lambda-Ausdruck aufzurufen und gleichzeitig die Abfrage in T-SQL zu übersetzen. Dies funktioniert, weil der Wrapper beim Konvertieren in den Ausdrucksbaum alle Vorkommen der Invoke-Methode durch Ausdrucksbäume des aufgerufenen Lambda-Ausdrucks ersetzt und diese Ausdrücke an DLINQ übergibt, der die erweiterte Abfrage in T-SQL übersetzen kann.

+0

Also, wie benutze ich den param? 'location (j) .MeetingLocation.Name' oder' location.MeetingLocation.Name' ist nicht gültig –

+0

@jimmy_b, Ich habe meine Antwort aktualisiert – octavioccl

+0

Invoke() gibt eine System.Linq.Expressions.Expression nicht das Objekt aus der Funktion –

Verwandte Themen