Exemplarische Vorgehensweise: Zugreifen auf einen OData-Dienst mithilfe von Typanbietern (F#)
OData, oder Open Data Protocol, ist ein Protokoll zur Datenübertragung im Internet.Viele Datenanbieter bieten Zugriff auf ihre Daten, indem sie einen OData-Webdienst veröffentlichen.Mithilfe der Datentypen, die vom ODataService-Typanbieter automatisch generiert werden, können Sie in F# 3.0 auf Daten in jeder OData-Quelle zugreifen.Weitere Informationen zu OData finden Sie unter Introducing OData.
In dieser exemplarischen Vorgehensweise wird erläutert, wie der ODataService-Typanbieter in F# verwendet wird, um Clienttypen für einen OData-Dienst zu generieren und die vom Dienst bereitgestellten Datenfeeds abzufragen.
Die exemplarische Vorgehensweise veranschaulicht die folgenden Aufgaben, die Sie in der angegebenen Reihenfolge ausführen müssen, um die exemplarische Vorgehensweise erfolgreich abzuschließen:
Configuring a client project for an OData service
Accessing OData types
Querying an OData service
Verifying the OData requests
Konfigurieren eines Clientprojekts für einen OData-Dienst
In diesem Schritt erstellen Sie ein Projekt, das einen OData-Typanbieter verwendet.
So konfigurieren Sie ein Clientprojekt für einen OData-Dienst
Öffnen Sie ein F#-Konsolenanwendungsprojekt, und fügen Sie anschließend einen Verweis auf die System.Data.Services.Client Frameworkassembly hinzu.
Unter Erweiterungen fügen Sie einen Verweis auf die FSharp.Data.TypeProviders-Assembly hinzu.
Zugreifen auf OData-Typen
In diesem Schritt erstellen Sie einen Typanbieter, der Zugriff auf die Typen und Daten eines OData-Diensts bietet.
So greifen Sie auf OData-Typen zu
Öffnen Sie im Code-Editor eine F#-Quelldatei, und geben Sie den folgenden Code ein.
open Microsoft.FSharp.Data.TypeProviders type Northwind = ODataService<"http://services.odata.org/Northwind/Northwind.svc/"> let db = Northwind.GetDataContext() let fullContext = Northwind.ServiceTypes.NorthwindEntities()
In diesem Beispiel haben Sie den F#-Typanbieter aufgerufen und ihn angewiesen, basierend auf dem angegebenen OData-URI einen Satz von Typen zu erstellen.Es sind zwei Objekte verfügbar, die Informationen zu den Daten enthalten. Das erste ist ein vereinfachter Datenkontext (db im Beispiel).Dieses Objekt enthält nur die Datentypen, die mit der Datenbank in Beziehung stehen, einschließlich der Typen für Tabellen und Feeds.Das andere Objekt (fullContext in diesem Beispiel) ist eine Instanz von DataContext und enthält viele zusätzliche Eigenschaften, Methoden und Ereignisse.
Abfragen eines OData-Diensts
In diesem Schritt verwenden Sie F#-Abfrageausdrücke, um den OData-Dienst abzufragen.
So fragen Sie einen OData-Dienst ab
Nachdem Sie den Typanbieter eingerichtet haben, können Sie einen OData-Dienst abfragen.
OData unterstützt nur eine Teilmenge der verfügbaren Abfrageoperationen.Im Folgenden werden die unterstützten Operationen und die zugehörigen Schlüsselwörter aufgeführt:
Projektion (select)
Filtern (where, unter Verwendung von Zeichenfolgen und Datumsoperationen)
Paging (skip, take)
Sortierung (orderBy, thenBy)
AddQueryOption und Expand, die OData-spezifische Vorgänge sind
Weitere Informationen finden Sie unter LINQ Considerations.
Wenn Sie alle Einträge aus einem Feed oder einer Tabelle abrufen möchten, verwenden Sie die einfachste Form des Abfrageausdrucks, wie im folgenden Code gezeigt:
query { for customer in db.Customers do select customer } |> Seq.iter (fun customer -> printfn "ID: %s\nCompany: %s" customer.CustomerID customer.CompanyName printfn "Contact: %s\nAddress: %s" customer.ContactName customer.Address printfn " %s, %s %s" customer.City customer.Region customer.PostalCode printfn "%s\n" customer.Phone)
Geben Sie die gewünschten Felder oder Spalten in einem Tupel nach dem select-Schlüsselwort an.
query { for cat in db.Categories do select (cat.CategoryID, cat.CategoryName, cat.Description) } |> Seq.iter (fun (id, name, description) -> printfn "ID: %d\nCategory: %s\nDescription: %s\n" id name description)
Formulieren Sie Bedingungen mit einer where-Klausel.
query { for employee in db.Employees do where (employee.EmployeeID = 9) select employee } |> Seq.iter (fun employee -> printfn "Name: %s ID: %d" (employee.FirstName + " " + employee.LastName) (employee.EmployeeID))
Formulieren Sie eine Teilzeichenfolgen-Bedingung mit der Contains-Methode.Die folgende Abfrage gibt alle Produkte mit der Zeichenfolge "Chef" im Namen zurück.Beachten Sie auch die Verwendung von GetValueOrDefault.Der Wert von UnitPrice kann NULL sein. Sie müssen den Wert also entweder über die Value-Eigenschaft abrufen oder den Aufruf GetValueOrDefault verwenden.
query { for product in db.Products do where (product.ProductName.Contains("Chef")) select product } |> Seq.iter (fun product -> printfn "ID: %d Product: %s" product.ProductID product.ProductName printfn "Price: %M\n" (product.UnitPrice.GetValueOrDefault()))
Verwenden Sie die EndsWith-Methode, um anzugeben, dass eine Zeichenfolge mit einer bestimmten Teilzeichenfolge endet.
query { for product in db.Products do where (product.ProductName.EndsWith("u")) select product } |> Seq.iter (fun product -> printfn "ID: %d Product: %s" product.ProductID product.ProductName printfn "Price: %M\n" (product.UnitPrice.GetValueOrDefault()))
Kombinieren Sie Bedingungen in einer where-Klausel mit dem &&-Operator.
// Open this module to use the nullable operators ?> and ?<. open Microsoft.FSharp.Linq.NullableOperators let salesIn1997 = query { for sales in db.Category_Sales_for_1997 do where (sales.CategorySales ?> 50000.00M && sales.CategorySales ?< 60000.0M) select sales } salesIn1997 |> Seq.iter (fun sales -> printfn "Category: %s Sales: %M" sales.CategoryName (sales.CategorySales.GetValueOrDefault()))
Die Operatoren ?> und ?< sind Operatoren, die NULL-Werte zulassen.Ihnen steht ein vollständiger Satz an Gleichheits- und Vergleichsoperatoren zur Verfügung, die NULL-Werte zulassen.Weitere Informationen finden Sie unter Linq.NullableOperators-Modul (F#).
Verwenden Sie den sortBy-Abfrageoperator, um eine Reihenfolge anzugeben, und thenBy, um eine weitere Ebene für die Reihenfolge hinzuzufügen.Beachten Sie auch die Verwendung des Tupels im select-Teil der Abfrage.Dies bedeutet, dass die Abfrage ein Tupel als Elementtyp verwendet.
printfn "Freight for some orders: " query { for order in db.Orders do sortBy (order.OrderDate.Value) thenBy (order.OrderID) select (order.OrderDate, order.OrderID, order.Customer.CompanyName) } |> Seq.iter (fun (orderDate, orderID, company) -> printfn "OrderDate: %s" (orderDate.GetValueOrDefault().ToString()) printfn "OrderID: %d Company: %s\n" orderID company)
Ignorieren Sie eine Anzahl von Datensätzen mit dem skip-Operator, und verwenden Sie den take-Operator, um anzugeben, wie viele Datensätze zurückgegeben werden sollen.Auf diese Weise können Sie eine seitenweise Darstellung für Datenfeeds implementieren.
printfn "Get the first page of 2 employees." query { for employee in db.Employees do take 2 select employee } |> Seq.iter (fun employee -> printfn "Name: %s ID: %d" (employee.FirstName + " " + employee.LastName) (employee.EmployeeID)) printfn "Get the next 2 employees." query { for employee in db.Employees do skip 2 take 2 select employee } |> Seq.iter (fun employee -> printfn "Name: %s ID: %d" (employee.FirstName + " " + employee.LastName) (employee.EmployeeID))
Überprüfen der OData-Anforderung
Jede OData-Abfrage wird in einen bestimmten OData-Anforderungs-URI übersetzt.Sie können den URI überprüfen, z. B. zu Debuggingzwecken, indem Sie dem SendingRequest-Ereignis des vollständigen Datenkontextobjekts einen Ereignishandler hinzufügen.
So überprüfen Sie eine OData-Anforderung
Um den OData-Anforderungs-URI zu überprüfen, verwenden Sie folgenden Code:
// The DataContext property returns the full data context. db.DataContext.SendingRequest.Add (fun eventArgs -> printfn "Requesting %A" eventArgs.Request.RequestUri)
Die Ausgabe des vorherigen Codes lautet:
Requesting http://services.odata.org/Northwind/Northwind.svc/Orders()?$orderby=ShippedDate&$select=OrderID,ShippedDate