Überlegungen zu LINQ (WCF Data Services)
Dieses Thema enthält Informationen dazu, wie LINQ-Abfragen bei der Verwendung des WCF Data Services -Clients verfasst und ausgeführt werden, und zu den Einschränkungen, die gelten, wenn Sie einen Datendienst, der Open Data Protocol (OData) implementiert, mithilfe von LINQ abfragen. Weitere Informationen über zum Verfassen und Ausführen von Abfragen für einen OData -basierten Datendienst finden Sie unter Abfragen des Datendiensts (WCF Data Services).
Verfassen von LINQ-Abfragen
LINQ ermöglicht es Ihnen, Abfragen für eine Auflistung von Objekten zu verfassen, die IEnumerable implementiert. Sowohl das Dialogfeld Dienstverweis hinzufügen in Visual Studio als auch das Tool "DataSvcUtil.exe" dienen zum Generieren einer Darstellung eines OData -Diensts als Entitätscontainerklasse, die von DataServiceContext erbt, und von Objekten, die die zurückgegebenen Entitäten in Feeds darstellen. Diese Tools generieren auch Eigenschaften der Entitätscontainerklasse für die Auflistungen, die als Feeds vom Dienst verfügbar gemacht werden. Jede Eigenschaft der Klasse, die den Datendienst kapselt, gibt eine DataServiceQuery zurück. Da die DataServiceQuery-Klasse die von LINQ definierte IQueryable-Schnittstelle implementiert, können Sie mit WCF Data Services eine LINQ-Abfrage für vom Datendienst verfügbar gemachte Feeds verfassen. Diese Abfrage wird von der Clientbibliothek in einen Abfrageanforderungs-URI übersetzt, der bei der Ausführung an den Datendienst gesendet wird.
Hinweis: |
---|
In der LINQ-Syntax können mehr Abfragen ausgedrückt werden als in der von OData -Datendiensten verwendeten URI-Syntax. Wenn die Abfrage keinem URI im Zieldatendienst zugeordnet werden kann, wird eine NotSupportedException ausgelöst. Weitere Informationen finden Sie unter unter Unsupported LINQ Methods in diesem Thema. |
Das folgende Beispiel zeigt eine LINQ-Abfrage, die Orders
mit Frachtkosten über $30 zurückgibt und die Ergebnisse nach dem Lieferdatum sortiert (beginnend mit dem aktuellsten Lieferdatum):
Dim selectedOrders = From o In context.Orders _
Where (o.Freight > 30) _
Order By o.ShippedDate Descending _
Select o
var selectedOrders = from o in context.Orders
where o.Freight > 30
orderby o.ShippedDate descending
select o;
Diese LINQ-Abfrage wird in den folgenden Abfrage-URI übersetzt, der für den auf Northwind basierenden Schnellstart-Datendienst ausgeführt wird:
https://localhost:12345/Northwind.svc/Orders?Orderby=ShippedDate&?filter=Freight gt 30
Weitere allgemeine Informationen zu LINQ finden Sie unter Language-Integrated Query (LINQ).
Mit LINQ können Sie Abfragen sowohl unter Verwendung der im obigen Beispiel gezeigten sprachspezifischen deklarativen Abfragesyntax als auch mit einem als Standardabfrageoperatoren bezeichneten Satz von Abfragemethoden verfassen. Eine Abfrage, die dem obigen Beispiel funktional entspricht, kann wie im folgenden Beispiel dargestellt auch nur mithilfe der methodenbasierten Syntax verfasst werden:
Dim selectedOrders = context.Orders _
.Where(Function(o) o.Freight.Value > 30) _
.OrderByDescending(Function(o) o.ShippedDate)
var selectedOrders = context.Orders
.Where(o => o.Freight > 30)
.OrderByDescending(o => o.ShippedDate);
Der WCF Data Services -Client kann beide Abfragearten in einen Abfrage-URI übersetzen, und Sie können eine LINQ-Abfrage erweitern, indem Sie Abfragemethoden an einen Abfrageausdruck anfügen. Wenn Sie LINQ-Abfragen verfassen, indem Sie Methodensyntax an einen Abfrageausdruck oder eine DataServiceQuery anfügen, werden die Vorgänge dem Abfrage-URI in der Reihenfolge hinzugefügt, in der Methoden aufgerufen werden. Dies hat die gleiche Funktion wie das Aufrufen der AddQueryOption-Methode zum Hinzufügen der einzelnen Abfrageoptionen zum Abfrage-URI.
Ausführen von LINQ-Abfragen
Wenn bestimmte LINQ-Abfragemethoden wie First oder Single an die Abfrage angefügt werden, führt dies dazu, dass die Abfrage ausgeführt wird. Eine Abfrage wird auch ausgeführt, wenn Ergebnisse implizit aufgezählt werden, z. B. während einer foreach-Schleife oder wenn die Abfrage einer List-Auflistung zugewiesen wird. Weitere Informationen finden Sie unter Abfragen des Datendiensts (WCF Data Services).
Der Client führt eine LINQ-Abfrage in zwei Teilen aus. Nach Möglichkeit werden LINQ-Ausdrücke in einer Abfrage zuerst auf dem Client ausgewertet, und anschließend wird eine URI-basierte Abfrage generiert und zur Auswertung anhand der Daten im Dienst an den Datendienst gesendet. Weitere Informationen finden Sie im Abschnitt Client versus Server Execution unter Abfragen des Datendiensts (WCF Data Services).
Wenn eine LINQ-Abfrage nicht in einen OData -kompatiblen Abfrage-URI übersetzt werden kann, wird beim Ausführen der Abfrage eine Ausnahme ausgelöst. Weitere Informationen finden Sie unter Abfragen des Datendiensts (WCF Data Services).
LINQ-Abfragebeispiele
Die Beispiele in den folgenden Abschnitten veranschaulichen die Arten von LINQ-Abfragen, die für einen OData -Dienst ausgeführt werden können.
Filtern
In den LINQ-Abfragebeispielen in diesem Abschnitt werden Daten in dem vom Dienst zurückgegebenen Feed gefiltert.
Die folgenden Beispiele zeigen funktional gleichwertige Abfragen, durch die zurückgegebene Orders
-Entitäten so gefiltert werden, dass nur Aufträge mit Frachtkosten über $30 zurückgegeben werden:
Verwendung der LINQ-Abfragesyntax:
Dim filteredOrders = From o In context.Orders Where o.Freight.Value > 30 Select o
var filteredOrders = from o in context.Orders where o.Freight > 30 select o;
Verwendung von LINQ-Abfragemethoden:
Dim filteredOrders = context.Orders.Where(Function(o) o.Freight.Value > 0)
var filteredOrders = context.Orders .Where(o => o.Freight > 30);
$filter-Option für die URI-Abfragezeichenfolge:
' Define a query for orders with a Freight value greater than 30. Dim filteredOrders _ = context.Orders.AddQueryOption("$filter", "Freight gt 30M")
// Define a query for orders with a Freight value greater than 30. var filteredOrders = context.Orders.AddQueryOption("$filter", "Freight gt 30M");
Die obigen Beispiele werden alle in den Abfrage-URI übersetzt: https://localhost:12345/northwind.svc/Orders()?$filter=Freight gt 30M
.
Sortieren
Die folgenden Beispiele zeigen funktional gleichwertige Abfragen, durch die zurückgegebene Daten in absteigender Reihenfolge nach dem Firmennamen und der Postleitzahl sortiert werden:
Verwendung der LINQ-Abfragesyntax:
Dim sortedCustomers = From c In context.Customers Order By c.CompanyName Ascending, c.PostalCode Descending Select c
var sortedCustomers = from c in context.Customers orderby c.CompanyName ascending, c.PostalCode descending select c;
Verwendung von LINQ-Abfragemethoden:
Dim sortedCustomers = context.Customers.OrderBy(Function(c) c.CompanyName) _ .ThenByDescending(Function(c) c.PostalCode)
var sortedCustomers = context.Customers.OrderBy(c => c.CompanyName) .ThenByDescending(c => c.PostalCode);
$orderby-Option für die URI-Abfragezeichenfolge:
Dim sortedCustomers = context.Customers _ .AddQueryOption("$orderby", "CompanyName, PostalCode desc")
var sortedCustomers = context.Customers .AddQueryOption("$orderby", "CompanyName, PostalCode desc");
Die obigen Beispiele werden alle in den Abfrage-URI übersetzt: https://localhost:12345/northwind.svc/Customers()?$orderby=CompanyName,PostalCode desc
.
Projektion
Die folgenden Beispiele zeigen funktional gleichwertige Abfragen, durch die zurückgegebene Daten in den enger gefassten CustomerAddress
-Typ projiziert werden:
Verwendung der LINQ-Abfragesyntax:
Dim projectedQuery = From c In context.Customers Select New CustomerAddress With { .CustomerID = c.CustomerID, .Address = c.Address, .City = c.City, .Region = c.Region, .PostalCode = c.PostalCode, .Country = c.Country }
var projectedQuery = from c in context.Customers select new CustomerAddress { CustomerID = c.CustomerID, Address = c.Address, City = c.City, Region = c.Region, PostalCode = c.PostalCode, Country = c.Country };
Verwendung von LINQ-Abfragemethoden:
Dim projectedQuery = context.Customers.Where(Function(c) c.Country = "Germany") _ .Select(Function(c) New CustomerAddress With { .CustomerID = c.CustomerID, .Address = c.Address, .City = c.City, .Region = c.Region, .PostalCode = c.PostalCode, .Country = c.Country })
var projectedQuery = context.Customers.Where(c => c.Country == "Germany") .Select(c => new CustomerAddress { CustomerID = c.CustomerID, Address = c.Address, City = c.City, Region = c.Region, PostalCode = c.PostalCode, Country = c.Country});
Hinweis: |
---|
Die $select-Abfrageoption kann einem Abfrage-URI nicht mit der AddQueryOption-Methode hinzugefügt werden. Es wird empfohlen, die Select-LINQ-Methode zu verwenden, damit der Client die $select-Abfrageoption im Anforderungs-URI generiert. |
Die obigen Beispiele werden beide in den Abfrage-URI übersetzt: "https://localhost:12345/northwind.svc/Customers()?$filter=Country eq 'GerGerm'&$select=CustomerID,Address,City,Region,PostalCode,Country"
.
Clientpaging
Die folgenden Beispiele zeigen funktional gleichwertige Abfragen, durch die eine Seite sortierter Order-Entitäten angefordert wird, die 25 Aufträge enthält und auf der die ersten 50 Aufträge übersprungen werden:
Anwendung von Abfragemethoden auf eine LINQ-Abfrage:
Dim pagedOrders = (From o In context.Orders Order By o.OrderDate Descending Select o) _ .Skip(50).Take(25)
var pagedOrders = (from o in context.Orders orderby o.OrderDate descending select o).Skip(50).Take(25);
$skip- und $top-Optionen für die URI-Abfragezeichenfolge:
Dim pagedOrders = context.Orders _ .AddQueryOption("$orderby", "OrderDate desc") _ .AddQueryOption("$skip", 50) _ .AddQueryOption("$top", 25) _
var pagedOrders = context.Orders .AddQueryOption("$orderby", "OrderDate desc") .AddQueryOption("$skip", 50) .AddQueryOption("$top", 25);
Die obigen Beispiele werden beide in den Abfrage-URI übersetzt: https://localhost:12345/northwind.svc/Orders()?$orderby=OrderDate desc&$skip=50&$top=25
.
Erweitern
Beim Abfragen eines OData -Datendiensts können Sie anfordern, dass mit der Zielentität der Abfrage verknüpfte Entitäten in den zurückgegebenen Feed eingeschlossen werden. Die Expand-Methode wird in der DataServiceQuery für die in der LINQ-Abfrage angegebene Entität aufgerufen, und der Name der verknüpften Entitätenmenge wird als path-Parameter angegeben. Weitere Informationen finden Sie unter Laden von verzögertem Inhalt (WCF Data Services).
Die folgenden Beispiele zeigen funktional gleichwertige Möglichkeiten zur Verwendung der Expand-Methode in einer Abfrage:
In der LINQ-Abfragesyntax:
Dim ordersQuery = From o In context.Orders.Expand("Order_Details") Where o.CustomerID = "ALFKI" Select o
var ordersQuery = from o in context.Orders.Expand("Order_Details") where o.CustomerID == "ALFKI" select o;
Mit LINQ-Abfragemethoden:
Dim ordersQuery = context.Orders.Expand("Order_Details") _ .Where(Function(o) o.CustomerID = "ALFKI")
var ordersQuery = context.Orders.Expand("Order_Details") .Where(o => o.CustomerID == "ALFKI");
Die obigen Beispiele werden beide in den Abfrage-URI übersetzt: https://localhost:12345/northwind.svc/Orders()?$filter=CustomerID eq 'ALFKI'&$expand=Order_Details
.
Nicht unterstützte LINQ-Methoden
Die folgende Tabelle enthält die Klassen von LINQ-Methoden, die nicht unterstützt werden und nicht in eine Abfrage für einen OData -Dienst eingeschlossen werden können:
Vorgangstyp | Nicht unterstützte Methode |
---|---|
Mengenoperatoren |
Alle Mengenoperatoren werden nicht für eine DataServiceQuery unterstützt. Dazu zählen folgende Operatoren: |
Sortierungsoperatoren |
Die folgenden Sortierungsoperatoren, die IComparer erfordern, werden für eine DataServiceQuery nicht unterstützt: |
Projektions- und Filterungsoperatoren |
Die folgenden Projektions- und Filterungsoperatoren, die ein Positionsargument akzeptieren, werden für eine DataServiceQuery nicht unterstützt: |
Gruppierungsoperatoren |
Alle Gruppierungsoperatoren werden nicht für eine DataServiceQuery unterstützt. Dazu zählen folgende Operatoren: Gruppierungsvorgänge müssen auf dem Client ausgeführt werden. |
Aggregatoperatoren |
Alle Aggregatoperatoren werden nicht für eine DataServiceQuery unterstützt. Dazu zählen folgende Operatoren: Aggregatvorgänge müssen entweder auf dem Client ausgeführt oder von einem Dienstvorgang gekapselt werden. |
Pagingoperatoren |
Die folgenden Pagingoperatoren werden nicht für eine DataServiceQuery unterstützt:
Hinweis:
Pagingoperatoren, die für eine leere Sequenz ausgeführt werden, geben NULL zurück.
|
Andere Operatoren |
Die folgenden anderen Operatoren werden nicht für eine DataServiceQuery unterstützt: |
Unterstützte Ausdrucksfunktionen
Die folgenden CLR-Methoden und -Eigenschaften (Common Language Runtime) werden unterstützt, da sie zum Einschließen in den Anforderungs-URI für einen OData -Dienst in einen Abfrageausdruck übersetzt werden können:
String-Member | Unterstützte OData -Funktion |
---|---|
string concat(string p0, string p1) |
|
bool substringof(string p0, string p1) |
|
bool endswith(string p0, string p1) |
|
int indexof(string p0, string p1) |
|
int length(string p0) |
|
string replace(string p0, string find, string replace) |
|
string substring(string p0, int pos) |
|
string substring(string p0, int pos, int length) |
|
string tolower(string p0) |
|
string toupper(string p0) |
|
string trim(string p0) |
DateTime-Member1 | Unterstützte OData -Funktion |
---|---|
int day(DateTime p0) |
|
int hour(DateTime p0) |
|
int minute(DateTime p0) |
|
int month(DateTime p0) |
|
int second(DateTime p0) |
|
int year(DateTime p0) |
1Die entsprechenden Time- und Date-Eigenschaften von Microsoft.VisualBasic.DateAndTime und die DatePart-Methode in Visual Basic werden ebenfalls unterstützt.
Math-Member | Unterstützte OData -Funktion |
---|---|
decimal ceiling(decimal p0) |
|
double ceiling(double p0) |
|
decimal floor(decimal p0) |
|
double floor(double p0) |
|
decimal round(decimal p0) |
|
double round(double p0) |
Expression-Member | Unterstützte OData -Funktion |
---|---|
bool isof(type p0) |
Der Client kann möglicherweise auch weitere CLR-Funktionen auf dem Client auswerten. Für einen Ausdruck, der nicht auf dem Client ausgewertet und nicht in einen gültigen URI für die Auswertung auf dem Server übersetzt werden kann, wird eine NotSupportedException ausgelöst.
Siehe auch
Konzepte
Abfragen des Datendiensts (WCF Data Services)
Abfrageprojektionen (WCF Data Services)
Objektmaterialisierung (WCF Data Services)