2007-07-28

DataContext

Die DataContext Klasse dient als eine Brücke zwischen der Applikation und der Datenbank. Seine aktive Rolle ermöglicht die Verknüpfungen zwischen der Entity Klassen und der Datenbanktabellen herzustellen.

Im Kontext der LINQ to SQL existiert pro Instanz von DataContext Klasse eine Verbindung zu einer relationalen Datenbank. Für die Verbindung eingesetzte Connection Objekt ist vom Typ IDbConnection definiert und somit bleibt LINQ Datenbankprodukt unabhängig.

Bei LINQ to SQL Version wird nur der SQL Server unterstützt. Aber es ist möglich, für die anderen Datenbankprodukte spezifische LINQ Provider zu entwickeln.

Der Zweck von DataContext ist, die Anfragen an die Datenbank weiterzugeben und aus dem Resultat dieser Anfragen die Entity Objekte zu erstellen.


In unsere Applikation schreiben wir LINQ Ausdrücke. Diese LINQ Ausdrücke werden von DataContext in die SQL Abfragen umgewandelt und an die Datenbank weitergegeben. Aus der Datenbank ermittelte Datensätze werden über das DataContext Objekt an die Entity Objekte weitergegeben. Diese Objekte werden nur erstellt, wenn die Abfrage auch Datensätze zurückgeliefert hat. Nach dem die Entity Objekte erstellt sind, stehen uns die Daten in Objekt orientierte Form für die Weiterverwendung bereit.

Mit DataContext können Sie nicht nur lesende Anfragen gegen die Daten erstellen sondern auch die Änderungen an den Daten können an die Datenbank weitergegeben werden. Nach dem die Daten in den Entity Objekten sind, werden diese Objekte vom zugehörenden DataContext Objekt überwacht.

Das DataContext Objekt kann es unterscheiden, ob ein Objekt gelöscht, neu erstellt oder geändert wurde. Dieser Fähigkeit hilft dem, die entsprechenden SQL Statements für die Datenbank zu erstellen. Für die unterliegende Datenbank werden die CRUD SQL Ausdrücke vom DataContext im Hintergrund generiert und für die entsprechende Änderung eingesetzt.

CRUD steht für die grundlegenden vier Datenbankoperationen:
· Create: Datensatz anlegen
· Read: Datensatz abfragen
· Update: Datensatz aktualisieren
· Delete: Datensatz löschen

Die Metadaten von unseren Entity Klassen helfen den DataContext die nötigen Verknüpfungen mit den Datenbanktabellen herzustellen. So weiß das DataContext Objekt welche Entity Klasse mit welcher Datenbanktabelle verknüpft ist und welche Daten in welche Datenbanktabelle weitergeben müssen.

Die LINQ Expression wird nicht an der Deklarationsstelle ausgeführt sondern der Zugriff auf die Datenbank erfolgt beim ersten Zugriff auf die Entity Objekte. Wenn Sie die Objekte mit einer foreach Schleife auswerten, wird der Zugriff auf die Datenbank erst an dem Punkt erfolgen. Dieser Vorgang ist auch unter dem Begriff Deferred Query Evaluation bekannt.

List planeten = new List()
{"Merkur", "Venus", "Erde", "Mars",
"Jupiter", "Saturn", "Uranus", "Neptun"};

// LINQ Expression wird hier definiert...
var query = from planet in planeten select planet;

// LINQ Expression wird erst hier ausgeführt....
foreach (var planet in query)
{
Console.WriteLine(planet);
}

Es gibt bei den Aggregat Operatoren eine Ausnahme. Bei verwendung von Aggreagat Operatoren wie Count, Min, Max und Average wird der LINQ Ausdruck sofort an der Stelle ausgeführt.

// LINQ Expression wird hier definiert und ausgeführt...
var count = (from planet in planeten
where planet.Length <= 5 select planet).Count(); Der Constructor der DataContext Klasse akzeptiert einen Connection String als Parameter. Sie können direkt beim erstellen ein DataContext Objekt den Connection String Ihrer Datenbank als Parameter übergeben. string connStr = @"Data Source=DBServer; Initial Catalog=AdventureWorks; Integrated Security=True"; DataContext db = new DataContext(connStr); Mit Hilfe der Log Eigenschaft von DataContext Klassen können Sie den generierten SQL Ausdrücke ausgeben. Dieser Möglichkeit kann beim Debugging Prozess behilflich sein, wenn Sie wissen möchten, wie der generierte SQL Ausdruck aussieht. string connStr = @"Data Source=.; Initial Catalog=AdventureWorks; Integrated Security=True"; DataContext db = new DataContext(connStr); db.Log = Console.Out; Die GetQueryText Methode der DataContext Klasse kann auch für die Ermittlung der SQL Abfragen verwendet werden. Dieser Methode liefert SQL Ausdrücke für die lesenden Zugriffe auf die Datenbank. var query = from p in product select p; Console.WriteLine(db.GetQueryText(query)); Für die schreibenden Zugriffe kann die GetChangeText Methode verwendet werden. Dieser Methode liefert die INSERT, UPDATE und DELETE SQL Ausdrücke, die vom DataContext Objekt im Hintergrund erstellt werden. Console.WriteLine(db.GetChangeText()); Mit Microsoft SQL Server gelieferte SQL Server Profiler kann natürlich auch für das Überwachen der generierten SQL Ausdrücke verwendet werden. An dieser Stelle empfehle ich sogar, dass Sie während der Entwicklung von Ihrer Applikation öfters mit SQL Server Profiler arbeiten. So können Sie an die Datenbank übergegebene SQL Ausdrücke überwachen und die von Profiler erstellten Auswertungen für die Optimierung Ihrer Datenbank verwenden. Mit der folgenden Grafik wird der Ablauf einer LINQ Abfrage im groben Dargestellt:
Abbildung: Ablauf LINQ to SQL Abfrage

Die einzelnen Schritte im Detail:
1. Innerhalb unseres Applikation definieren wir den LINQ Statement. Unser LINQ Statement wird erst beim ersten Gebrauch gegen die Datenbank ausgeführt. Dieser Vorgang wird als Deferred Query Evalution genannt.

2. Das DataContext Objekt generiert im Hintergrund gemäß unser LINQ Statement den nötigen SQL Statement. Für die Generierung der SQL Statement macht das DataContext Objekt gebrauch von unsere Entity Klasse und deren Metadaten.

3. Die Datensätze werden aus der Datenbank ermittelt.

4. Wenn Datensätze vorhanden sind, werden diese Datensätze an die Objekte weitergegeben. In diesem Schritt geschieht auch die Umwandlung von den Datensätzen in die Objekte. Dieser Vorgang ist möglich, weil die Entity Klassen mit Metadaten bestückt sind. In diese Metadaten sind Angaben zu den Verknüpfungen zwischen den Datenbankfelder und Objekt Eigenschaften oder Objekt Felder vorhanden.

Wenn Sie mit Hilfe der Designer Ihre Entity Klassen erstellen, dann wird der Designer eine Klasse erstellen, welche von der DataContext Klasse abgeleitet ist.

Und wie sieht es mit Stored Procedures aus? Mit LINQ to SQL können Sie auch die Stored Procedures verwenden.

No comments: