2016-07-28 36 views
-3

Angenommen, ich habe eine Tabelle mit 2 Tabellen in einer Funktion, die ein IQueryable zurückgibt, aber die Ausgabe ist ein benannter Typ, der keiner der beiden ist Tabellen:Können Sie einem IQueryable ein Where() hinzufügen, wenn das Feld nicht in der ausgewählten Ausgabe ist

var qry = from p in Persons 
      join h in Hobbies on p.PersonId equals h.PersonId 
      select new OutputType 
      { 
       Name = p.FirstName, 
       Hobby = h.HobbyName 
      } 

return qry 

ist jetzt Lassen Sie sagen, ich wollte diese Abfrage zurück nehmen und wie etwas zu tun:

var newQuery = qry.Where(p=>p.Age > 18) 

wie Sie dies ein Problem sehen kann, weil die IQueryable vom Typ Output ist, so kann ich füge keinen Ort in das Alter einer Person ein, es sei denn, ich würde das Alter zu OutputType hinzufügen.

Gibt es überhaupt einen 'Einbruch' in die IQueryable-Ausdrucksbaumstruktur und das Hinzufügen eines Lambdas, das die darin angegebene Quellensammlung abfragt und eine Where-Klausel hinzufügt? Oder muss ich dem Ausgabetyp ein Where-Feld hinzufügen, obwohl ich nicht daran interessiert bin, es zu projizieren?

+3

Während ich vermute, dass Sie einen Weg, dies zu tun finden könnten, wenn man wirklich wollte, es ist wirklich nur ein Zeichen dafür, dass Ihr Design fehlerhaft ist, und Sie müssen Ihren Code so strukturieren, dass Sie die Filterung tun vor Projektion der Sequenz. – Servy

+0

Vielleicht könnten Sie etwas umgestalten und den Wert für 'Personen' eingeben. Also anstelle von 'Personen' würden Sie' Personen übergeben. Wo (p => p.Age> 18) ' –

+0

Das Beispiel, das ich gab, war genau das, ein Beispiel. Ich zeigte nur das Konzept, nicht die Verwendung. Der eigentliche Fall ist ein 4-Tabellen-Join über einer bestehenden Oracle-Altdatenbank. Ich habe 3 verschiedene Varianten derselben (großen) Abfrage, die sich nur in der Where-Klausel von nicht-projektierten Werten aus verschiedenen Tabellen unterscheidet. Ich versuche, die Redundanz im Code zu reduzieren, damit ich nicht mehrere große LINQ-Abfragen verwalten kann. Die erste Antwort unten ist sehr hilfreich, da ich nicht dafür bestraft werde, dass ich ein Feld zu einem frühen Zeitpunkt hinzugefügt und es letztendlich nicht projiziert habe. Der einzige Nachteil ist, dass mehrere neue Typen erstellt werden müssen. –

Antwort

1

Es ist einfacher, Ihre Ansicht später einzuschränken, als zu versuchen, zurückzugehen. Hier ist ein abgespecktes Beispiel, wie ich Methoden zur Wiederverwendung schichten möchte, so dass sie nette SQL ausspucken.

Linq-to-entity benachteiligt Sie nicht für die Auswahl der zusätzlichen Spalte früh. Wie Sie sehen können, enthält der SQL-Wert die Cost-Spalte in der Constraint, aber nicht in der Auswahl.

SELECT 
    1 AS [C1], 
    [Extent1].[ComponentNumber] AS [ComponentNumber], 
    [Extent1].[ComponentDescription] AS [ComponentDescription], 
    [Extent1].[ComponentPrice] AS [ComponentPrice] 
FROM [dbo].[Component] AS [Extent1] 
WHERE [Extent1].[ComponentCost] < @p__linq__0 
+0

Das einzige Negative ist die Erstellung all dieser benannten Typen für jede Ebene, aber die Antwort ist sehr solide. Es ist wirklich schade, dass die Bits des IQueryable bei einer Methodenrückgabe so schwer zugänglich sind, aber ich vermutete, dass dies der Fall sein würde. Vielen Dank! –