Skip to Content

LinQ

Was ist LinQ?

LinQ steht für Language Integrated Query und ist eine Sprachintegrierte Abfragesyntax für .NET. Es ermöglicht es strukturierte, typsichere Abfragen über loakle Objekte (Arrays, Listen) und entfernte Datenquellen (XML, Datenbanken)

Es nutzt das IEnumerable<T> Interface für lokale Sequenzen und IQueryable<T> für Datenbanken.

Welche zwei Syntax Formen gibt es für LinQ-Abfragen?

Methoden-Syntax:

Nutzt Lambda Ausdrücke und Erweiterungsmethoden (z.B. .Where()) und wird oft bevorzugt wegen besserer Verkettbarkeit.

var result = people.Where(person => person.Age > 18) .Select(person => person.Name).ToList();

Query-Syntax:

Nutzt SQL-ähnliche Syntax und wird oft bevorzugt wegen besserer Lesbarkeit. Der Compiler wandelt diese Abfragen dann in Methodenaufrufe um.

var result = from person in people where person.Age > 18 select person.Name;

Verzögerte Ausführung (Lazy Evaluation)

Abfragen werden nicht bei der Definition ausgeführt, sondern erst beim Abrufen der Ergebnisse. Die Variable merkt sich nur den Befehl der auszuführen ist. Erst wenn das Ergebnis benötigt wird, wird die Abfrage ausgeführt.

Beispiel hierfür ist die foreach Schleife.

var zahlen = new List<int> { 1, 2 }; var query = zahlen.Select(n => n * 10); zahlen.Add(3); foreach (var n in query) { Console.WriteLine(n); } // 10 20 30

Obwohl 3 später hinzugefügt wurde, wird es auch in der Ausgabe berücksichtigt, da die Query sich nur den Befehl merkt, aber noch nicht ausgeführt wurde bis foreach ausgeführt wird.

Ausnahmen:

Es gibt Methoden die eine sofortige Ausführung erzwingen. Dies passiert bei Methoden die ein einzelnes Element oder eine feste Sammlung erfordern.

Methoden die eine sofortige Ausführung erzwingen:

  • ToList(), ToArray(), ToDictionary(), ToHashSet(), ToLookup()
  • Count(), First(), Single(), ElementAt()
  • Sum(), Average(), Min(), Max()

Welche Rolle spielen Lambda-Ausdrücke in LinQ?

Lambda Ausdrücke wirken wie Callback Methoden um eigene Logik an den Operator zu übergeben.

var result = people.Where(person => person.Age > 18); // Für jede Person die älter als 18 ist, wird die Logik ausgeführt.

Was machen Where, Take und Skip?

  • Where: Filtert die Sequenz nach einer Bedingung.
  • Take(n): Liefert die ersten n Elemente und verwirft den Rest.
  • Skip(n): Liefert die Sequenz ab dem n-ten Element und verwirft den Rest.
var result = people.Where(person => person.Age > 18) .Take(10) .Skip(5) .ToList();

Was machen Select und SelectMany?

Select: Nimmt jedes Element aus einer Liste und macht daraus ein neues Element. Es ändert nicht die Anzahl an Elementen die rauskommen.

var personen = new[] { "Max Mustermann", "Erika Musterfrau", "Peter Pan" }; var personenNamen = personen.Select(person => person.Split(" ")); // ["Max", "Mustermann"], ["Erika", "Musterfrau"], ["Peter", "Pan"]

SelectMany: Nimmt jedes Element aus einer Liste und macht daraus eine neue Liste. Als Ergebnis erhält man eine flache Liste.

var personen = new[] { "Max Mustermann", "Erika Musterfrau", "Peter Pan" }; var personenNamen = personen.SelectMany(person => person.Split(" ")); // ["Max", "Mustermann", "Erika", "Musterfrau", "Peter", "Pan"]

Wie sortiert man eien Liste aufsteigend oder absteigend?

OrderBy: Sortiert die Liste aufsteigend.

var personen = new[] { "Max Mustermann", "Erika Musterfrau", "Peter Pan" }; var sortiertePersonen = personen.OrderBy(person => person.Length); // ["Peter Pan", "Max Mustermann", "Erika Musterfrau"]

OrderByDescending: Sortiert die Liste absteigend.

var personen = new[] { "Max Mustermann", "Erika Musterfrau", "Peter Pan" }; var sortiertePersonen = personen.OrderByDescending(person => person.Length); // ["Erika Musterfrau", "Max Mustermann", "Peter Pan"]

Wie sortiert man eine Liste nach mehreren Kriterien?

ThenBy: Sortiert die Liste nach einem zweiten Kriterium. Es wird nach dem ersten Kriterium angewendet und sortiert ein weiteres Kriterium wenn der erste Schlüssel gleich ist.

var personen = new[] { "Max Mustermann", "Erika Musterfrau", "Peter Pan" }; var sortiertePersonen = personen.OrderBy(person => person.Length).ThenBy(person => person.Name); // ["Peter Pan", "Max Mustermann", "Erika Musterfrau"]

ThenByDescending: Sortiert die Liste nach einem zweiten Kriterium absteigend.

var personen = new[] { "Max Mustermann", "Erika Musterfrau", "Peter Pan" }; var sortiertePersonen = personen.OrderBy(person => person.Length).ThenByDescending(person => person.Name); // ["Erika Musterfrau", "Max Mustermann", "Peter Pan"]

Unterschied zwischen First, Single und ElementAt?

  • First: Liefert das erste Element der Sequenz. Wenn das Element leer ist, wird eine Exception geworfen.
  • Single: Liefert das einzige Element der Sequenz. Wenn das Element leer ist oder es mehrere Elemente gibt, wird eine Exception geworfen.
  • ElementAt: Liefert das Element an der angegebenen Position. Wenn die Position außerhalb des Bereichs ist, wird eine Exception geworfen.
var personen = new[] { "Max Mustermann", "Erika Musterfrau", "Peter Pan" }; var person = personen.First(); // "Max Mustermann" var person = personen.Single(); // Exception var person = personen.ElementAt(1); // "Erika Musterfrau"

Alle haben eine OrDefault() Methode die ein Standardwert zurückgibt wenn die Sequenz leer ist und keine Exception wirft.

Was bewirken Dinstinct, Union, Intersect und Except?

Distinct: Entfernt Duplikate aus der Sequenz.

var personen = new[] { "Max Mustermann", "Erika Musterfrau", "Peter Pan", "Max Mustermann" }; var distinctPersonen = personen.Distinct(); // ["Max Mustermann", "Erika Musterfrau", "Peter Pan"]

Union: Fügt zwei Sequenzen zusammen und entfernt Duplikate.

var personen1 = new[] { "Max Mustermann", "Erika Musterfrau" }; var personen2 = new[] { "Peter Pan", "Max Mustermann" }; var unionPersonen = personen1.Union(personen2); // ["Max Mustermann", "Erika Musterfrau", "Peter Pan"]

Intersect: Gibt die Elemente zurück, die in beiden Sequenzen vorkommen.

var personen1 = new[] { "Max Mustermann", "Erika Musterfrau" }; var personen2 = new[] { "Peter Pan", "Max Mustermann" }; var intersectPersonen = personen1.Intersect(personen2); // ["Max Mustermann"]

Except: Gibt die Elemente zurück, die in der ersten Sequenz vorkommen, aber nicht in der zweiten Sequenz.

var personen1 = new[] { "Max Mustermann", "Erika Musterfrau" }; var personen2 = new[] { "Peter Pan", "Max Mustermann" }; var exceptPersonen = personen1.Except(personen2); // ["Erika Musterfrau"]

Aggregations Methoden

  • Count: Zählt die Anzahl der Elemente in der Sequenz.
  • Sum: Summiert die Elemente der Sequenz.
  • Average: Berechnet den Durchschnitt der Elemente der Sequenz.
  • Min: Findet das kleinste Element in der Sequenz.
  • Max: Findet das größte Element in der Sequenz.
var personen = new[] { "Max Mustermann", "Erika Musterfrau", "Peter Pan" }; var anzahlPersonen = personen.Count(); // 3 var summeAlter = personen.Sum(person => person.Age); // 100 var durchschnittAlter = personen.Average(person => person.Age); // 33.33333333333333 var minAlter = personen.Min(person => person.Age); // 20 var maxAlter = personen.Max(person => person.Age); // 40

Was prüfen Any, All und Contains?

Alle Methoden geben einen bool Wert zurück.

  • Any: Prüft ob mindestens ein Element in der Sequenz die Bedingung erfüllt.
  • All: Prüft ob alle Elemente in der Sequenz die Bedingung erfüllen.
  • Contains: Prüft ob ein bestimmtes Element in der Sequenz vorhanden ist.
int[] numbers = { 1, 2, 3, 4, 5 }; var anyNumber = numbers.Any(number => number > 3); // true var allNumbers = numbers.All(number => number > 0); // true var containsNumber = numbers.Contains(3); // true

Was macht der GroupBy Operator?

GroupBye transformiert eine flasche Liste in eine Folge von Gruppen basierend auf einem Schlüssel. Jede Gruppe hat eine Key Eigenschaft und enthält eine List der zugehörigen Elemente.

string[] dateien = { "report.txt", "report.pdf", "report.xlsx", "invoice.pdf" }; var gruppierteDateien = dateien.GroupBy(datei => Path.GetExtension(datei)); // [["txt", "report.txt"], ["pdf", "report.pdf", "invoice.pdf"], ["xlsx", "report.xlsx"]] foreach(var gruppe in gruppierteDateien) { Console.WriteLine(gruppe.Key); foreach(var datei in gruppe) { Console.WriteLine(datei); } } // txt // report.txt // pdf // report.pdf // invoice.pdf // xlsx // report.xlsx

Was ist der Unterschied zwischen Join und GroupJoin?

Join

Der Join enstpricht dem SQL INNER JOIN. Er erzeugt eine flache Ergebnisliste.

Verhalten:

Er kombiniert Elemente aus Liste A (Outer) und Liste B (Inner) nur dort, wo die Schlüssel übereinstimmen. Elemente aus Liste A die keine Partner in Liste B haben, entfallen. Elemente aus Liste A, die mehrere Partner in Liste B haben tauchen im Ergebnis mehrfach auf.

var studenten = new[] { new { Id = 1, Name = "Max Mustermann" }, new { Id = 2, Name = "Erika Musterfrau" }, new { Id = 3, Name = "Peter Pan" } }; var kurse = new[] { new { StudentId = 1, Titel = "Mathematik" }, new { StudentId = 2, Titel = "Deutsch" }, }; // Methoden Syntax var ergebnis = studenten.Join( kurse, s => s.Id, k => k.StudentId, (s, k) => new { s.Name, k.Titel } ); // Query Syntax var ergebnis = from s in studenten join k in kurse on s.Id equals k.StudentId select new { s.Name, k.Titel }; // [{"Name": "Max Mustermann", "Titel": "Mathematik"}, {"Name": "Erika Musterfrau", "Titel": "Deutsch"}]

GroupJoin

Der GroupJoin behält die Struktur der ersten Liste bei und hängt die passenden Elemente der zweiten Liste als Collection an.

Verhalten: Er nimmt jedes Element aus Liste A. Für jedes Element aus A werden alle passenden Elemente aus Liste B gesucht. Auch wenn ein Element aus Liste A keine passenden Elemente in Liste B hat, wird es in das Ergebnis aufgenommen.

Als Ergebnis erhält man eine Liste von Objekten, wobei jedes Objekt ein IEnumerable enthält.

var ergebnis = studenten.GroupJoin( kurse, s => s.Id, k => k.StudentId, (s, kListe) => new { Student = s.Name, BelegteKurse = kListe } ); // Query Syntax var ergebnis = from s in studenten join k in kurse on s.Id equals k.StudentId group k by s.Name into g select new { Student = g.Key, BelegteKurse = g.Select(k => k.Titel) }; // [{"Student": "Max Mustermann", "BelegteKurse": ["Mathematik, Englisch"]}, {"Student": "Erika Musterfrau", "BelegteKurse": ["Deutsch"]}, {"Student": "Peter Pan", "BelegteKurse": []}]

Wofür nutzt man ToList, ToArray oder ToDictionary?

Diese Methoden werden verwendet um eine verzögerte Ausführung zu beenden und die Ergebnisse sofort im Speicher zu materialisieren als Liste, Array oder Dictionary. Man verwendet diese Methoden um unnötige mehrfaches Ausführen der Abfrage zu vermeiden oder Index Zugriffe zu ermöglichen.

Last updated on