Frage

Ich brauche die untergeordneten Elemente eines Unternehmens in Linq unter Verwendung einer einzigen Linq-Abfrage zu filtern. Ist das möglich?

Angenommen, ich habe zwei verknüpften Tabellen. Verse und VerseTranslations. Das Unternehmen erstellt von LINQ to SQL ist so, dass ich einen Vers zum Gegenstand haben, die ein Kind Objekt enthält, das eine Sammlung von VerseTranslation ist.

Wenn ich nun die Folge Linq-Abfrage haben

var res = from v in dc.Verses
                  where v.id = 1
                  select v;

Ich erhalte eine Sammlung von Versen mit id = 1 und jedes Vers-Objekt enthält alle das Kind von VerseTranslations Objekten.

Was will ich auch tun, ist Filter, die Child-Liste Verse Übersetzungen.

Bisher ist der einzige Weg, ich in der Lage gewesen, mit zu kommen ist durch einen neuen Typen Anonymous oder anderweitig verwenden. Wie folgt

var res= from v in dc.Verses
                   select new myType
                   {
                       VerseId = v.VerseId,
                       VText = v.Text,
                       VerseTranslations = (from trans in v.VerseTranslations
                                               where languageId==trans.LanguageId
                                               select trans
                   };

Der obige Code funktioniert, aber ich hatte eine neue Klasse für sie zu erklären. Gibt es keine Möglichkeit, es in einer solchen Art und Weise, so dass die Filterung auf der untergeordneten Tabelle zu tun, kann in der ersten Linq-Abfrage eingebaut werden, so dass keine neuen Klassen deklariert werden müssen.

Viele Grüße, MAC

War es hilfreich?

Lösung

Also ich habe es endlich dank arbeiten, um die von Shiraz gegeben Zeiger.

        DataLoadOptions options = new DataLoadOptions();
        options.AssociateWith<Verse>(item => item.VerseTranslation.Where(t => languageId.Contains(t.LanguageId)));

        dc.LoadOptions = options;

        var res = from s in dc.Verse
                   select s;

Dies erfordert keine Projektion oder eine neue Erweiterungsklassen verwenden.

Vielen Dank für Ihre Eingabe Menschen.

Andere Tipps

Filtern auf der beiliegenden Sammlung des Objekts,

var res = dc.Verses
            .Update(v => v.VerseTranslations 
                      =  v.VerseTranslations
                          .Where(n => n.LanguageId == languageId));

Durch die Verwendung von Erweiterungsmethode "Update" von HookedOnLinq

public static class UpdateExtensions {

    public delegate void Func<TArg0>(TArg0 element);

    /// <summary>
    /// Executes an Update statement block on all elements in an IEnumerable<T> sequence.
    /// </summary>
    /// <typeparam name="TSource">The source element type.</typeparam>
    /// <param name="source">The source sequence.</param>
    /// <param name="update">The update statement to execute for each element.</param>
    /// <returns>The numer of records affected.</returns>
    public static int Update<TSource>(this IEnumerable<TSource> source, Func<TSource> update) {
        if (source == null) throw new ArgumentNullException("source");
        if (update == null) throw new ArgumentNullException("update");
        if (typeof(TSource).IsValueType) 
            throw new NotSupportedException("value type elements are not supported by update.");

        int count = 0;
        foreach(TSource element in source) {
            update(element);
            count++;
        }
        return count;
    }
}

Wenn dies aus einer Datenbank kommt, könnten Sie Ihre erste Anweisung ausgeführt werden.

Dann eine Last tun oder mit einer Include von VerseTranslations Where-Klausel.

http://msdn.microsoft.com/en-us/library /bb896249.aspx

Haben Sie eine Beziehung im Modell zwischen Verse haben und VerseTranslations. In diesem Fall könnte dies funktionieren:

var res= from v in 
dc.Verses.Include("VerseTranslations").Where(o => languageId==o.LanguageId)
select v;
  

Gibt es keine Möglichkeit, es in ein solches zu tun   derart, dass die Filterung auf dem   Kind-Tabelle kann in die eingearbeitet werden   erste Linq-Abfrage, so dass keine neuen   Klassen haben erklärt werden?

Technisch gesehen ist die Antwort nein. Wenn Sie versuchen, mehr Daten als eine einzige Einheit Objekt zurückzukehren (Vers, VerseTranslation) halten kann, werden Sie irgendeine Art von Objekt „Projekt“ in benötigen. Sie können jedoch um explizit erklärt myType erhalten, indem einen anonymen Typ mit:

var res = from v in dc.Verses
          select new
          {
              Verse = v,
              Translations = (from trans in v.VerseTranslations
                              where languageId==trans.LanguageId
                              select trans).ToList()
          };

var first = res.First();
Console.WriteLine("Verse {0} has {1} translation(s) in language {2}.",
    first.Verse.VerseId, first.Translations.Count, languageId);

Der Compiler wird eine Klasse mit entsprechend typisierte Versen und Übersetzungen Eigenschaften für Sie generiert. Sie können diese Objekte für fast alles verwenden, solange Sie nicht namentlich auf die Art beziehen müssen (von einer benannten Methode zurückzukehren, zum Beispiel). So, während Sie nicht technisch eine Art „deklarieren“, verwenden Sie immer noch eine neue Art, die pro Ihre Spezifikation erzeugt werden.

Was eine einzelne LINQ-Abfrage verwendet wird, es hängt alles davon, wie Sie die Daten strukturiert werden sollen. Mir scheint es, wie Ihre ursprüngliche Abfrage am meisten Sinn macht: jede Verse mit einer gefilterten Liste von Übersetzungen paaren. Wenn Sie nur eine einzige Übersetzung pro Sprache erwarten, könnten Sie SingleOrDefault (oder FirstOrDefault) verwenden, um Ihre Unterabfrage zu glätten, oder einfach nur einen SelectMany wie folgt verwenden:

var res= from v in dc.Verses
         from t in v.VerseTranslations.DefaultIfEmpty()
         where t == null || languageId == t.LanguageId
         select new { Verse = v, Translation = t };

Wenn ein Vers mehrere Übersetzungen hat, dies wird wieder eine „Reihe“ für jeden Vers / Translation Paar. Ich benutze DefaultIfEmpty() als links, um sicherzustellen, kommen wir alle Verse erhalten, auch wenn sie eine Übersetzung sind vermisst.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top