Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort zur 6. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Das Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Strukturen und Enumerationen
7 Fehlerbehandlung und Debugging
8 Auflistungsklassen (Collections)
9 Generics – Generische Datentypen
10 Weitere C#-Sprachfeatures
11 LINQ
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 XML
15 Multithreading und die Task Parallel Library (TPL)
16 Einige wichtige .NET-Klassen
17 Projektmanagement und Visual Studio 2012
18 Einführung in die WPF und XAML
19 WPF-Layout-Container
20 Fenster in der WPF
21 WPF-Steuerelemente
22 Elementbindungen
23 Konzepte von WPF
24 Datenbindung
25 Weitere Möglichkeiten der Datenbindung
26 Dependency Properties
27 Ereignisse in der WPF
28 WPF-Commands
29 Benutzerdefinierte Controls
30 2D-Grafik
31 ADO.NET – Verbindungsorientierte Objekte
32 ADO.NET – Das Command-Objekt
33 ADO.NET – Der SqlDataAdapter
34 ADO.NET – Daten im lokalen Speicher
35 ADO.NET – Aktualisieren der Datenbank
36 Stark typisierte DataSets
37 Einführung in das ADO.NET Entity Framework
38 Datenabfragen des Entity Data Models (EDM)
39 Entitätsaktualisierung und Zustandsverwaltung
40 Konflikte behandeln
41 Plain Old CLR Objects (POCOs)
Stichwort

Download:
- Beispiele, ca. 62,4 MB

Jetzt Buch bestellen
Ihre Meinung?

Spacer
Visual C# 2012 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2012

Visual C# 2012
Rheinwerk Computing
1402 S., 6., aktualisierte und erweiterte Auflage 2013, geb., mit DVD
49,90 Euro, ISBN 978-3-8362-1997-6
Pfeil 38 Datenabfragen des Entity Data Models (EDM)
Pfeil 38.1 Abfragen mit LINQ to Entities
Pfeil 38.1.1 Allgemeine Begriffe in LINQ
Pfeil 38.1.2 Einfache Abfragen
Pfeil 38.1.3 Navigieren in Abfragen
Pfeil 38.1.4 Aggregatmethoden
Pfeil 38.1.5 Joins in LINQ definieren
Pfeil 38.1.6 In Beziehung stehende Daten laden
Pfeil 38.2 Abfragen mit Entity SQL
Pfeil 38.2.1 Ein erstes Beispiel mit Entity SQL
Pfeil 38.2.2 Die fundamentalen Regeln der Entity-SQL-Syntax
Pfeil 38.2.3 Filtern mit Entity SQL
Pfeil 38.2.4 Parametrisierte Abfragen
Pfeil 38.3 Der EntityClient-Provider
Pfeil 38.3.1 Verbindungen mit »EntityConnection«
Pfeil 38.3.2 Die Klasse »EntityCommand«
Pfeil 38.4 Abfrage-Generator-Methoden (QueryBuilder-Methoden)
Pfeil 38.5 SQL-Direktabfragen

Rheinwerk Computing - Zum Seitenanfang

38.2 Abfragen mit Entity SQLZur nächsten Überschrift

Entity SQL (kurz: eSQL) ist eine Alternative zu LINQ to Entities. Entity SQL ist ein datenbankunabhängiger SQL-Dialekt, der direkt mit dem konzeptionellen Modell arbeitet. Die Syntax ähnelt der des traditionellen T-SQL und ist auf die Belange der Entitäten hin geprägt. Allerdings wird das einfache Übernehmen einer T-SQL nach Entity SQL zu einem Fehler führen – und natürlich auch in umgekehrter Richtung.

Warum eine weitere Abfragevariante? Zunächst einmal ist festzustellen, dass die Entwicklung von Entity SQL begann, als es LINQ noch nicht gab. Dass man später trotz LINQ Entity SQL weiterverfolgte, hat einen recht einfachen Grund: LINQ ist Teil der Sprache von C# geworden, wird aber von den vielen anderen .NET-fähigen Sprachen unterstützt. Zudem werden in manchen Situationen keine Entitäten (also Objekte) benötigt – beispielsweise wenn nur »nackte« Daten gewünscht werden und die Materialisierung in Entitäten nicht von Interesse ist, ähnlich wie bei den DataReader-Objekten von ADO.NET. Solche Anforderungen können nur mit Entity SQL gelöst werden. Ein weiterer Vorteil von Entity SQL ist, dass eine Abfrage erst zur Laufzeit erzeugt werden kann. Das ist mit LINQ to Entities nicht möglich.

Entity SQL unterstützt nur Abfragen. Es gibt daher in Entity SQL zwar ein SELECT, aber keine Aktualisierungsstatements wie UPDATE, INSERT oder DELETE.


Rheinwerk Computing - Zum Seitenanfang

38.2.1 Ein erstes Beispiel mit Entity SQLZur nächsten ÜberschriftZur vorigen Überschrift

Sehen Sie sich noch einmal Abbildung 37.13 im vorhergehenden Kapitel an. Sie können darin erkennen, dass Sie die Object Services des Entity Frameworks ansprechen können oder die Entity-SQL-Abfrage dem EntityClient-Provider übergeben können. Das folgende erste Beispiel einer Entity-SQL-Abfrage soll die Object Services nutzen.

using (NorthwindEntities context = new NorthwindEntities()) 
{
var query = "SELECT VALUE p FROM NorthwindEntities.Products AS p " +
"WHERE p.UnitPrice > 50";
ObjectQuery<Product> products = context.CreateQuery<Product>(query);
foreach (Product item in products)
Console.WriteLine(item.ProductName);
}

Listing 38.21 Einfache Entity-SQL-Abfrage

Die Variable query beschreibt das Entity-SQL-Statement. Anschließend wird ein Objekt vom Typ ObjectQuery erzeugt. Dazu wird auf dem Objektkontext dessen Methode CreateQuery aufgerufen und das Entity-SQL-Statement übergeben. Sie sehen, das Entity-SQL-Statement sieht anders aus als ein T-SQL-Statement. Das sollte aber auch nicht verwundern, denn Entitäten unterscheiden sich deutlich von relationalen Daten.

In Listing 38.21 wird ein Objekt vom Typ ObjectQuery durch den Aufruf der Methode CreateQuery auf den Objektkontext erzeugt. Sie können alternativ auch den Konstruktor der Klasse ObjectQuery benutzen, dem Sie zuerst die das Entity SQL beschreibende Zeichenfolge und anschließend die Referenz auf den Objektkontext übergeben. Bezogen auf Listing 38.21 sähe die Anweisung wie folgt aus:

ObjectQuery<Product> products = new ObjectQuery<Product>(query, context);

Rheinwerk Computing - Zum Seitenanfang

38.2.2 Die fundamentalen Regeln der Entity-SQL-SyntaxZur nächsten ÜberschriftZur vorigen Überschrift

Sehen wir uns das Entity-SQL-Statement des Listings 38.21 genauer an und ignorieren dabei die WHERE-Klausel.

SELECT VALUE p FROM NorthwindEntities.Products AS p

In jeder Entity-SQL-Abfrage muss das Entitätenmodell angegeben werden, auf das sich die Abfrage bezieht. In unserem Fall ist das NorthwindEntities.Products. Die Groß- oder Kleinschreibung findet hier keine Berücksichtigung.

Die VALUE-Klausel wird benötigt, wenn die einzelnen Resultate nur einen bestimmten Typ beschreiben. Dabei kann es sich um eine Entität, eine Eigenschaft oder auch eine Liste von Entitäten handeln. Um alle Produktbezeichner abzufragen, wären die folgenden Anweisungen notwendig:

var query = "SELECT VALUE p.ProductName FROM NorthwindEntities.Products AS p";
var products = context.CreateQuery<string>(query);

Ohne VALUE wird das Resultat der Abfrage tabellarisch geliefert. Um die Daten zu erhalten, muss dann durch die Zeilen und Spalten navigiert werden.

Gehören mehrere Elemente zu einem Rückgabeelement, können Sie auf VALUE verzichten. Angenommen, jedes Element der Ergebnismenge soll durch ProductName und UnitPrice beschrieben werden, würde das Entity-SQL-Statement wie folgt lauten:

var query = "SELECT p.ProductName, p.UnitPrice FROM ... AS p";

Etwas Probleme macht nun die Ausgabe an der Konsole, denn wir haben es hier mit einer Projektion zu tun, die unter LINQ zu einem anonymen Typ wird, womit LINQ problemlos umgehen kann. Entity SQL kann das jedoch nicht. Andererseits benötigt die Methode CreateQuery eine genaue Typangabe. Die Lösung ist sehr einfach: Tragen Sie den Typ DbDataRecord ein, der sich im Namespace System.Data.Common befindet. Der Code würde einschließlich des Entity-SQL-Statements wie folgt lauten:

using (NorthwindEntities context = new NorthwindEntities())
{
var query = "SELECT p.ProductName, p.UnitPrice FROM ... AS p";
var products = new ObjectQuery<DbDataRecord>(query, context);
foreach (var item in products)
Console.WriteLine(item.GetValue(0));
}

Listing 38.22 Entity-SQL-Statement

Den Einsatz von VALUE kennen Sie nun. Erwähnt werden muss in diesem Statement noch, dass mit AS eine Variable deklariert wird, die die Ergebnismenge darstellt.

Entity SQL unterstützt nicht das »*«-Zeichen, um alle Spalten an den Aufrufer zurückzuliefern. Das bedeutet, dass alle Spalten, auf die der Aufrufer zugreifen soll, ausdrücklich genannt werden müssen.


Rheinwerk Computing - Zum Seitenanfang

38.2.3 Filtern mit Entity SQLZur nächsten ÜberschriftZur vorigen Überschrift

Eine der wichtigsten Operationen einer Abfrage ist das Filtern von Daten. Wie in der klassischen SQL-Syntax verwendet auch Entity SQL zum Filtern von Daten die WHERE-Klausel. Das folgende Listing zeigt, wie diejenigen Produkte in die Ergebnismenge geschrieben werden können, die mit Discontinued=true als Auslaufprodukte gekennzeichnet sind.

using (NorthwindEntities context = new NorthwindEntities())
{
string query = "SELECT VALUE p FROM northwindentities.products AS p " +
"WHERE p.Discontinued = true";
ObjectQuery<Product> products = new ObjectQuery<Product>(query, context);
foreach (var item in products)
Console.WriteLine(item.ProductName);
}

Listing 38.23 Alle Auslaufprodukte mit Entity SQL herausfiltern

Alle Filteroperatoren von Entity SQL aufzuführen würde den Rahmen sprengen. Nichtsdestotrotz sollen hier die wichtigsten erwähnt werden.

Logische Operatoren

Sie können in Entity SQL die üblichen logischen Operatoren NOT, OR und AND benutzen. Sollten mehrere logische Operatoren verwendet werden, spiegelt die Reihenfolge NOT, OR und AND auch die Prioritätsreihenfolge wider. In C# ist es auch möglich, diese Operatoren durch die sprachspezifischen zu ersetzen. Daher können Sie eine Entity-SQL-Abfrage entweder mit

SELECT VALUE p FROM NorthwindEntities.Products AS p 
WHERE p.UnitPrice > 20 AND p.UnitsInStock <10

oder mit

SELECT VALUE p FROM NorthwindEntities.Products AS p 
WHERE p.UnitPrice > 20 && p.UnitsInStock <10

formulieren.

Vergleichsoperatoren

Zum Vergleich von Werten bietet Entity SQL die üblichen »Verdächtigen« an (siehe Tabelle 38.2):

Tabelle 38.2 Logische Operatoren von Entity SQL

Operator Beschreibung

<

Kleiner als ...

>

Größer als ...

>=

Größer als oder gleich ...

<=

Kleiner als oder gleich ...

=

Gleich. In C# kann für diesen Operator auch »==« benutzt werden.

<>

Ungleich. In C# kann für diesen Operator auch »!=« benutzt werden.

Mustervergleiche mit Zeichenfolgen

Auch hinsichtlich des Mustervergleichs mit LIKE ähnelt Entity SQL dem klassischen SQL. Mit Platzhaltern wird geprüft, ob die Zeichenkette passend zu einer Vorgabe ist.

Die folgende Entity-SQL-Abfrage liefert beispielsweise alle Artikel, die mit dem Buchstaben »C« im Produktnamen beginnen.

SELECT VALUE p FROM ... AS p WHERE p.ProductName LIKE 'C%'

Im folgenden Statement wird der Filter erweitert in der Weise, dass alle Produkte, deren erster Buchstabe des Produktbezeichners im Bereich von »A« bis »D« liegt, zurückgeliefert werden.

SELECT VALUE p FROM ... AS p WHERE p.ProductName LIKE '[A-D]%'

Das »%«-Zeichen dient als Platzhalter für x-beliebig viele Zeichen, mit den eckigen Klammern wird der gewünschte Bereich definiert.

Die Festlegung des Bereichs kann auch negiert werden. Wollen Sie beispielsweise alle Produkte abfragen, die sich nicht im Bereich »A« bis »D« befinden, muss die WHERE-Klausel wie folgt definiert werden:

... WHERE p.ProductName LIKE '[^A-D]%'

Bereiche von Werten prüfen

Um zu prüfen, ob ein Wert sich innerhalb eines bestimmten Bereichs befindet, benutzen Sie den BETWEEN-Operator. Das folgende Statement liefert alle Produkte zurück, deren Preis zwischen einschließlich 10 und 20 liegt.

SELECT VALUE p FROM ... AS p WHERE p.UnitPrice BETWEEN 10 AND 20

Anzumerken sei noch, dass sich der BETWEEN-Operator mit NOT negieren lässt.

Der Operator IS NULL

Tabellenspalten einer Datenbank können den Wert NULL haben. Mit den logischen Operatoren wie »=« oder »<>« ein Feld auf NULL hin zu prüfen, erzeugt zwar keinen Fehler, liefert aber andererseits auch nichts zurück, weil ein Wert weder NULL noch ungleich NULL sein kann. Um gegen NULL zu prüfen, gibt es daher in Entity SQL den Operator IS NULL.

Das nächste Entity-SQL-Statement fragt nach allen Datensätzen, die im Feld CategoryID den Wert NULL haben. Standardmäßig hat das kein Datensatz in der Tabelle Products. Wenn Sie tatsächlich ein Ergebnis sehen wollen, sollten Sie vorher eine Datenzeile hinzufügen, die in dem betreffenden Feld NULL aufweist.

SELECT VALUE p FROM ... AS p WHERE p.CategoryID IS NULL

Rheinwerk Computing - Zum Seitenanfang

38.2.4 Parametrisierte AbfragenZur vorigen Überschrift

Die meisten Filter einer Datenabfrage sind nicht statisch, sondern dynamisch. Mit anderen Worten heißt das, dass die meisten Abfragen parametrisiert sind. Auch in diesen Fällen unterstützt uns das ObjectQuery-Objekt durch die Bereitstellung einer Parameter-Collection, die über die Eigenschaft Parameters angesprochen werden kann. Die Parameter werden, angelehnt an T-SQL, mit einem @-Zeichen eingeleitet und mit der Add-Methode der Parameterliste des ObjectQuery-Objekts hinzugefügt. Dabei muss jedoch beachtet werden, dass beim Hinzufügen das @-Zeichen nicht mit angegeben wird.

using (NorthwindEntities context = new NorthwindEntities())
{
string query = "SELECT VALUE p FROM NorthwindEntities.Products AS p " +
"WHERE p.UnitPrice > @preis";
ObjectQuery<Product> products = context.CreateQuery<Product>(query);
products.Parameters.Add(new ObjectParameter("preis", 50));
foreach (Product item in products)
Console.WriteLine("{0,-35}{1}", item.ProductName, item.UnitPrice);
}

Listing 38.24 Parametrisierte Abfrage mit Entity SQL



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.

<< zurück
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Visual C# 2012

Visual C# 2012
Jetzt Buch bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Rheinwerk-Shop: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Rheinwerk-Shop: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: C++ Handbuch






 C++ Handbuch


Zum Rheinwerk-Shop: C/C++






 C/C++


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo





Copyright © Rheinwerk Verlag GmbH 2013
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern