2013-08-09 5 views
5

filtern Können sagen, wir haben:Linq Ausdruck eine Liste von Unternehmen Sammlung und pflegen Liste der Entitäten

public class Foo 
{ 
    public long Id { get; set; } 
    public string Name { get; set; } 
    public ICollection<Bar> { get; set; } 
} 

public class Bar 
{ 
    public long Id { get; set; } 
    public int Age { get; set; } 

    public virtual Foo { get; set; } 
    public long FooId { get; set; } 
} 

Unsere Daten etwas wie folgt aussehen: (nehmen List<Foo>)

// Forget the syntax, just to demonstrate data 
foo[0] = new Foo{ Id = 1, Name = "A", Bar = { collection of Bars with Ages over 10 }}; 
foo[1] = new Foo{ Id = 2, Name = "B", Bar = { collection of Bars with Ages over 20 }}; 
foo[2] = new Foo{ Id = 3, Name = "C", Bar = { collection of Bars with Ages under 10 }}; 

Nun, sagen wir, ich wollte alle diese Foo s aber mit ihrer Bar s nur einschließlich einer Bar mit einem Alter zwischen 5-25.

Für so etwas würde ich rückwärts arbeiten und alle Bars bekommen, dann alle assoziierten Foos zu diesen Bars bekommen, und die Bars wieder auf Foo abbilden. Scheint übermäßig kompliziert, als es sein sollte.

Um mehr klar zu sein - Alle Foos mit nur ihre Bars im Alter zwischen 5 und 25 :)

+0

http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b – Androiderson

+0

Ihre Frage Art unklar ist - tun Sie alle 'Foo's wollen nur ihre' Bar's mit Alter zwischen 5 und 25 oder willst du nur die 'Foo's' mit' Bar's im Alter zwischen 5 und 25? –

+0

Eine Möglichkeit, die noch nicht vorgeschlagen wurde, ist die Implementierung einer Erweiterungsmethode auf Foo mit einer Deklaration etwa wie folgt: 'GetBarsBetween (int lower, int obe);' und einfach diese Extensionsmethode zum Filtern und Abrufen der korrekten Balken verwenden ein Foo. Dann können Sie einfach alle Foo's where foo.GetBarsBetween (5, 25) .Any() 'auswählen. Dies erfordert keine zusätzliche Speicherzuordnung oder Umstrukturierung Ihrer aktuellen Objekte. Zwei Nachteile, Sie können nicht einfach vorhandenen Code verwenden, um mit den gefilterten Balken zu arbeiten, und die Rechenzeit ist etwas höher. – Polity

Antwort

4

Wenn Sie alle Foo ‚s und ihre einzige Bar‘ auswählen möchten s zwischen dem Alter von 5 und 25:

var results = 
    from f in db.Foos 
    select new 
    { 
     f.Id, 
     f.Name, 
     Bars = f.Bars.Where(b => b.Age >= 5 && b.Age <= 25) 
    }; 

Dies wird einen anonymen Typ als Ergebnis. Wenn Sie eine benannte Art erstellen müssen (zum Beispiel, wenn Sie das Ergebnis aus einer Funktion als List<T> zurückkehren müssen) sollten Sie wahrscheinlich eine einfache genannte Art für dieses Ergebnis Set erstellen:

public class FooWithFilteredBarResult // replace with whatever name you like 
{ 
    public long Id { get; set; } 
    public string Name { get; set; } 
    public IEnumerable<Bar> { get; set; } 
} 


List<FooWithFilteredBarResult> results = 
    (from f in db.Foos 
    select new FooWithFilteredBarResult 
    { 
     Id = f.Id, 
     Name = f.Name, 
     Bars = f.Bars.Where(b => b.Age >= 5 && b.Age <= 25) 
    }) 
    .ToList(); 
+0

'Let' trägt eine recht beachtliche Performance in linq zu Objekten, nur Heads-up. – doogle

+0

Die zweite Antwort auf Ihre Antworten ist, was ich suche. Gibt es eine Möglichkeit zu umgehen, alle Eigenschaften von Foo angeben zu müssen, sondern einfach "automatisch auswählen" und die Bedingung auf die Balken setzen? – Josh

+0

@Josh Nein, leider nicht, obwohl Sie immer versuchen könnten, sie später zu filtern, z. wie Sie die Ergebnisse bewerten. Außerdem müssen Sie nur die Eigenschaften von 'Foo' angeben, die Sie benötigen. Wenn es 50 andere Eigenschaften gibt, die Sie nicht interessieren, können Sie diese verlassen. –

1
var r = Foos.Select(x => new Foo() 
     { 
      Id = x.Id, 
      Name = x.Name, 
      Bars = x.Bars.Where(y => y.Age <= 25 && y.Age >= 5).ToList() 
     }); 
+0

Dies ist im Wesentlichen das gleiche wie @pswg Option # 2 Antwort, aber es lässt mich nicht ein neues Foo erstellen? Es besagt, dass die Entität oder der komplexe Typ nicht in einer LINQ to Entities-Abfrage erstellt werden kann. – Josh

+0

@Josh es scheint, wir haben zur gleichen Zeit eingereicht. Hmm..ich wusste nicht, dass du darüber sprichst, Datensätze über EF zu filtern. Lemme darüber nachdenken. – zsong

1

Dies wird auch nur wählen einzigartige Foo's.

bars.Where(b => b.Age >= 5 && b.Age <= 25).GroupBy(b => b.FooId).Select(g => g.FirstOrDefault().Foo).ToList(); 
+0

Ich bekomme die GroupBy. Warum der Select/FirstOrDefault? – Josh

+0

Um nur die eindeutigen Foo's auszuwählen, sonst könnten Sie mit Wiederholungen nach der Frage und der Struktur enden. – doogle

+0

Das scheint Bars zurückzugeben? – Josh

Verwandte Themen