11.2 LINQ to Objects
11.2.1 Musterdaten
Wir werden uns in den folgenden Abschnitten mit den wichtigsten Erweiterungsmethoden von LINQ beschäftigen. Dazu müssen wir uns noch eine passende Datenquelle beschaffen. Die meisten Beispiele in diesem Kapitel arbeiten daher mit Daten, die von einer Klassenbibliothek bereitgestellt werden. Sie finden das Projekt auf der Buch-DVD unter \Beispiele\Kapitel 11\Musterdaten. In der Anwendung sind die vier Klassen Customer, Product, Order und Service sowie die Enumeration Cities definiert.
public class Order {
public int OrderID { get; set; }
public int ProductID { get; set; }
public int Quantity { get; set; }
public bool Shipped { get; set; }
}
public class Customer {
public string Name { get; set; }
public Cities City { get; set; }
public Order[] Orders { get; set; }
}
public class Product {
public int ProductID { get; set; }
public string ProductName { get; set; }
public double Price { get; set; }
}
public enum Cities {
Aachen,
Bonn,
Köln
}
Listing 11.7 Die elementaren Klassen der »Musterdaten«
In der Klasse Service werden drei Arrays definiert, die mehrere Produkte, Kunden und Bestellungen beschreiben. Beachten Sie bitte, dass die einzelnen Bestellungen den Kunden direkt in einem Feld zugeordnet werden. Zudem sind in Service drei Methoden implementiert, die als Datenlieferant entweder die Liste der Kunden, der Bestellungen oder der Produkte zurückliefern. Sämtliche Klassenmitglieder sind statisch definiert.
public class Service {
public static Product[] GetProducts() { return product; }
public static Customer[] GetCustomers() { return customers; }
public static Order[] GetOrders() { return orders; }
public static Product[] product =
{
new Product{ ProductID = 1, ProductName = "Käse", Price = 10},
new Product{ ProductID = 2, ProductName = "Wurst", Price = 5},
new Product{ ProductID = 3, ProductName = "Obst", Price = 8.56},
new Product{ ProductID = 4, ProductName = "Gemüse", Price = 4},
new Product{ ProductID = 5, ProductName = "Fleisch", Price = 17.5},
new Product{ ProductID = 6, ProductName = "Süßwaren", Price = 3},
new Product{ ProductID = 7, ProductName = "Bier", Price = 2.8},
new Product{ ProductID = 8, ProductName = "Pizza", Price = 7}
};
public static Order[] orders =
{
new Order{ OrderID= 1, ProductID = 4, Quantity = 2, Shipped = true},
new Order{ OrderID= 2, ProductID = 1, Quantity = 1, Shipped = true},
new Order{ OrderID= 3, ProductID = 5, Quantity = 4, Shipped = false},
new Order{ OrderID= 4, ProductID = 4, Quantity = 5, Shipped = true},
new Order{ OrderID= 5, ProductID = 8, Quantity = 6, Shipped = true},
new Order{ OrderID= 6, ProductID = 3, Quantity = 3, Shipped = false},
new Order{ OrderID= 7, ProductID = 7, Quantity = 2, Shipped = true},
new Order{ OrderID= 8, ProductID = 8, Quantity = 1, Shipped = false},
new Order{ OrderID= 9, ProductID = 4, Quantity = 1, Shipped = false},
new Order{ OrderID= 10, ProductID = 1, Quantity = 8, Shipped = true},
new Order{ OrderID= 11, ProductID = 3, Quantity = 3, Shipped = true},
new Order{ OrderID= 12, ProductID = 6, Quantity = 6, Shipped = true},
new Order{ OrderID= 13, ProductID = 1, Quantity = 4, Shipped = false},
new Order{ OrderID= 14, ProductID = 6, Quantity = 3, Shipped = true},
new Order{ OrderID= 15, ProductID = 5, Quantity = 7, Shipped = true},
new Order{ OrderID= 16, ProductID = 1, Quantity = 9, Shipped = true}
};
public static Customer[] customers =
{
new Customer{ Name = "Herbert", City = Cities.Aachen,
Orders = new Order[]{orders[3], orders[2],orders[8], orders[10]}},
new Customer{ Name = "Willi", City = Cities.Köln,
Orders = new Order[]{orders[6], orders[7], orders[9] } },
new Customer{ Name = "Hans", City = Cities.Bonn,
Orders = new Order[]{orders[4], orders[11], orders[14] } },
new Customer{ Name = "Freddy", City = Cities.Bonn,
Orders = new Order[]{orders[1], orders[5], orders[13] } },
new Customer{ Name = "Theo", City = Cities.Aachen,
Orders = new Order[]{orders[15], orders[12] } }
};
}
Listing 11.8 Die Klasse »Service« der »Musterdaten«
Sollten Sie selbst in einem eigenen Projekt mit den Daten experimentieren, müssen Sie die Assembly Musterdaten.dll unter Verweise in das Projekt einbinden und den Namespace Musterdaten mit using bekannt geben.
11.2.2 Die allgemeine LINQ-Syntax
Viele der folgenden Listings in diesem Kapitel finden Sie auf der Buch-DVD in der Anwendung ..\Kapitel 11\Listings.
Die Beispiele sind entsprechend mit der Listing-Nummer gekennzeichnet. Wenn Sie die Listings auf der Buch-DVD ausprobieren wollen, müssen Sie nur die entsprechende Auskommentierung der Listing-Nummer aufheben.
Beginnen wir mit einer einfachen Abfrage, die alle bekannten Kunden aus den Musterdaten der Reihe nach ausgibt. Dabei soll sich die Ausgabe auf die Kunden beschränken, deren Name weniger als sechs Buchstaben hat. In die Ergebnismenge soll der Name des Kunden sowie sein Wohnort aufgenommen werden. Sie können die entsprechende LINQ-Abfrage auf zweierlei Arten definieren. Entweder als Abfrage-Syntax oder als Erweiterungsmethoden-Syntax. Sehen wir uns zuerst die Abfrage-Syntax an:
Customer[] customers = Service.GetCustomers();
var cust = from customer in customers
where customer.Name.Length < 6
select new { customer.Name, customer.City };
foreach (var item in cust)
Console.WriteLine("Name: {0}, Ort: {1}", item.Name, item.City);
Listing 11.9 Dieses Listing finden Sie auch auf der Buch-DVD.
Grundsätzlich beginnt eine LINQ-Abfrage mit from und nicht wie bei einem SQL-Statement mit select. Der Grund dafür ist, dass zuerst die Datenquelle ausgewählt sein muss, auf der alle nachfolgenden Operationen Element für Element ausgeführt werden. Das ist auch der Grund, warum die Datenquelle das Interface IEnumerable<T> implementieren muss.
Die Angabe der Datenquelle zu Beginn gestattet es uns darüber hinaus, mit der IntelliSense-Hilfe im Codeeditor zu arbeiten. Mit where wird das Filterkriterium beschrieben, und select legt fest, welche Daten tatsächlich in die Ergebnisliste eingetragen werden. Das Ergebnis wird einer implizit typisierten Variablen zugewiesen, die mit var beschrieben wird. Diese Anweisung könnte auch durch
IEnumerable<string> cust = from customer in customers ...
ersetzt werden, da eine LINQ-Abfrage als Resultat eine Liste liefert, die die Schnittstelle IEnumerable<T> implementiert.
In unserer Ergebnisliste wollen wir die einzelnen Customer-Objekte nicht mit allen ihren Eigenschaften aufnehmen. Um bestimmte Eigenschaften zu filtern, übergeben Sie dem select einen anonymen Typ, der sich aus den gewünschten Elementen zusammensetzt. In unserem Beispielcode handelt es sich um die Eigenschaften Name und City. Die Ausgabe der Ergebnismenge erfolgt in einer foreach-Schleife. Die Laufvariable wird vom Typ var deklariert.
Die zweite Variante ist die Erweiterungsmethoden-Syntax. Mit dieser können Sie die Abfrage auch wie folgt formulieren:
var cust = customers
.Where(customer => customer.Name.Length < 6)
.Select(c => new { c.Name, c.City });
Listing 11.10 Die Abfrage des Listings 11.9 als Erweiterungsmethoden-Syntax formuliert
Welche der beiden Varianten Sie bevorzugen, bleibt Ihnen überlassen. Die Abfrage-Syntax sieht auf den ersten Blick etwas einfacher aus, aber mit etwas Übung gewöhnen Sie sich auch schnell an die Erweiterungsmethoden-Syntax.
Zwischen der Abfrage-Syntax und der Erweiterungsmethoden-Syntax gibt es noch einen Unterschied zu beachten: Verwenden Sie nämlich die Abfrage-Syntax, müssen Sie auch select angeben, um damit den Typ der Ergebnisliste zu beschreiben. Bei Verwendung der Erweiterungsmethoden-Syntax ist jedoch die Angabe des Abfrageoperators Select nicht zwingend vorgeschrieben.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.