Lies in den Artikel rein und unten bekommst Du ein unschlagbares Angebot!
In den vorangegangenen Ausgaben von DATENBANKENTWICKLER haben Sie bereits erfahren, wie Sie per ADO.NET auf die Daten der Tabellen einer Datenbank zugreifen. Nun nutzen wir nicht mehr direkt ADO.NET, sondern das Entity Framework als Datenlieferant, welches eine ganz andere Art des Zugriffs ermöglicht. Dieser Artikel zeigt, wie Sie per C#-Konsolenanwendung auf die per Entity Data Model bereitgestellten Daten zugreifen.
Beispielprojekt
Das Beispielprojekt soll über ein geeignetes Entity Data Model auf die Tabellen einer LocalDB-Datenbank zugreifen. Wie Sie das Entity Data Model erstellen, beschreiben wir im Artikel Entity Data Model für eine Datenbank erstellen.
Alle Beispielmethoden finden Sie in der Klasse EDM_ZugriffPerCSharp_Beispiele.cs. Um die Beispiele auszuprobieren, starten Sie einfach das Projekt.
Aufruf der Beispielmethoden
Damit wir die nachfolgend programmierten Methoden einfach aufrufen können, verwenden wir wieder die bereits in früheren Artikeln verwendete Klasse Program mit einer Main-Methode, die alle öffentlichen, statischen Methoden aus öffentlichen Klassen auflistet und zur Ausführung anbietet. In einer neuen Klasse namens EDM_ZugriffPerCSharp_Beispiele.cs legen wir dann die später vorgestellten Methoden an.
LINQ to Entities
Die Abfragesprache für den Zugriff auf die Daten des Entity Frameworks und damit auf das Entity Data Model heißt LINQ to Entities.
Zugriff auf die Daten der Tabelle Anrede
Unter Access würden Sie nun, wenn Sie alle Datensätze einer Tabelle wie etwa Anrede durchlaufen wollten, ein Database-Objekt und ein Recordset-Objekt erzeugen, Letzteres mit einer entsprechenden SQL-Anweisung füllen und dann per VBA in einer Do While-Schleife durch die einzelnen Datensätze navigieren. Unter C# und dem Entity Framework sieht das etwas anders aus – im Überblick wie in Listing 1. Hier nutzen Sie ein automatisch generiertes Objekt, das die Klasse DbContext implementiert, die in unserem Fall beispielsweise Bestellverwaltung-Entities heißt.
public static void AlleAnredenAusgeben_ForEach() { BestellverwaltungEntities context = new BestellverwaltungEntities(); var anreden = context.Anreden; foreach (var anrede in anreden) { Console.WriteLine("{0} {1}", anrede.ID, anrede.Bezeichnung); } }
Listing 1: Methode zur Ausgabe aller Anreden der Beispieldatenbank
Wir erstellen ein neues Objekt auf Basis dieses Typs und speichern es in der Variablen context:
BestellverwaltungEntities context = new BestellverwaltungEntities();
Dann definieren wir eine Variable des Typs var und nennen diese anreden. Sie soll mit der Liste der Anreden des Objekts context gefüllt werden:
var anreden = context.Anreden;
Schließlich durchlaufen wir die Elemente der Auflistung anreden in einer foreach-Schleife und weisen das jeweils aktuelle Objekt der Variablen anrede zu. Innerhalb der Schleife geben wir dann die Werte der Eigenschaften ID und Bezeichnung aller Elemente aus:
foreach (var anrede in anreden) { Console.WriteLine("{0} {1}", anrede.ID, anrede.Bezeichnung); }
Das Ergebnis sieht etwa so aus:
1 Herr 2 Frau
Praktischerweise blendet Visual Studio beim Eingeben der Eigenschaften für das Objekt anrede per IntelliSense die verfügbaren Einträge ein (siehe Bild 1).
Bild 1: IntelliSense für den Datenzugriff
Fertig – damit wäre der erste Zugriff auf die Daten der Tabelle Anreden unserer Beispieldatenbank schon erledigt! Im Folgenden sehen wir uns nun weitere Möglichkeiten an.
Verbesserung: using verwenden
Damit die Verbindung zur Datenbank nach dem Abrufen der Daten wieder geschlossen wird, fassen Sie die für den Datenzugriff verwendeten Methoden in ein using-Konstrukt ein. Der Grund, ohne weitere Erläuterungen: Die DbContext-Klasse, von der unsere Klasse erbt, implementiert das Interface IDisposable. Die Nutzung solcher Objekte sollte man innerhalb der using-Direktive realisieren. Auf diese Weise wird beim Verlassen des von der using-Direktiven eingefassten Abschnitts auf jeden Fall die Dispose-Methode aufgerufen, was zum Beispiel die genutzten Ressourcen wieder freigibt. Die verbesserte Version des vorherigen Beispiels sieht nun wie in Listing 2 aus.
public static void AlleAnredenAusgeben_ForEach_Besser() { using (BestellverwaltungEntities context = new BestellverwaltungEntities()) { var anreden = context.Anreden; foreach (var anrede in anreden) { Console.WriteLine("{0} {1}", anrede.ID, anrede.Bezeichnung); } } Console.ReadLine(); }
Listing 2: Methode zur Ausgabe aller Anreden der Beispieldatenbank mit using
Achtung: Die using-Variante funktioniert nicht wie gewünscht, wenn Sie die der using-Direktiven übergebene Variable bereits vorher deklarieren, wie es hier der Fall ist. Die Variable existiert dann auch noch nach Verlassen von using:
BestellverwaltungEntities context = new BestellverwaltungEntities() using (context) { ... }
Kunden sortiert ausgeben
Wenn Sie die Daten einer Tabelle sortiert erhalten möchten, können Sie das durch eine Erweiterung einer Abfrage erreichen. Alle Kunden in unsortierter Reihenfolge würde folgendes Statement liefern:
var kunden = context.Kunden;
Wenn Sie eine Sortierung hinzufügen wollen, etwa nach dem Feld Nachname, haben Sie zwei Möglichkeiten – eine mit der Methodensyntax und eine mit der Abfragesyntax.
Abfragen mit der Methodensyntax
Für beide fügen Sie zunächst eine Referenz auf den Namespace System.Linq zur Klassendatei hinzu:
using System.Linq;
Nun erstellen Sie eine Methode wie in Listing 3. Der Unterschied zur Ermittlung der unsortierten Kunden liegt in der folgenden Zeile: