チュートリアル : 型プロバイダーを使用した OData サービスへのアクセス (F#)
OData (Open Data Protocol) は、インターネットでデータを転送するためのプロトコルです。 多くのデータ プロバイダーが、OData Web サービスを公開してデータへのアクセスを提供しています。 F# 3.0 では、ODataService 型プロバイダーによって自動生成されるデータ型を使用して、どの OData ソースからでもデータにアクセスできます。 OData の詳細については、「Introducing OData」を参照してください。
このチュートリアルでは、F# ODataService 型プロバイダーを使用して、OData サービスのクライアント型を生成し、サービスが提供するデータ フィードを照会する方法を示します。
このチュートリアルでは以下の作業について説明します。このチュートリアルを正しく行うには、これらの作業を順に行ってください。
OData サービスのクライアント プロジェクトの構成
OData 型へのアクセス
OData サービスの照会
OData 要求の確認
OData サービスのクライアント プロジェクトの構成
この手順では、OData 型プロバイダーを使用するようにプロジェクトを設定します。
OData サービスのクライアント プロジェクトを構成するには
F# コンソール アプリケーション プロジェクトを開き、System.Data.Services.Client Framework アセンブリへの参照を追加します。
[拡張機能] の下で、FSharp.Data.TypeProviders アセンブリへの参照を追加します。
OData 型へのアクセス
この手順では、OData サービスの型とデータへのアクセスを提供する型プロバイダーを作成します。
OData 型にアクセスするには
コード エディターで、F# ソース ファイルを開いて次のコードを入力します。
open Microsoft.FSharp.Data.TypeProviders type Northwind = ODataService<"http://services.odata.org/Northwind/Northwind.svc/"> let db = Northwind.GetDataContext() let fullContext = Northwind.ServiceTypes.NorthwindEntities()
この例では、F# 型プロバイダーを呼び出し、指定した OData URI に基づく一連の型を生成するように指示しました。 データに関する情報を含む 2 つのオブジェクトを使用できます。この例では、1 つは簡易データ コンテキストの db です。 このオブジェクトには、テーブルやフィードの型を含む、データベースに関連付けられているデータ型だけが含まれています。 この例の、もう 1 つのオブジェクト fullContext は DataContext のインスタンスで、追加のプロパティ、メソッド、イベントなどが多数含まれています。
OData サービスの照会
この手順では、F# クエリ式を使用して OData サービスを照会します。
OData サービスに照会するには
型プロバイダーを設定したので、OData サービスを照会できます。
OData は、使用可能なクエリ操作の一部のみをサポートしています。 次の操作と対応するキーワードがサポートされています。
プロジェクション (select)
フィルター処理 (where、文字列演算と日付演算を使用)
ページング (skip、take)
順序付け (orderBy、thenBy)
AddQueryOption および Expand (OData 固有の演算)
詳細については、「LINQ に関する留意点 (WCF Data Services)」を参照してください。
フィードまたはテーブルのすべてのエントリが必要な場合は、次のコードのように、クエリ式の最も単純な形式を使用してください。
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)
select キーワードの後にタプルを使用して、必要なフィールドまたは列を指定します。
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)
where 句を使用して、条件を指定します。
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))
Contains メソッドを使用して、クエリに部分文字列の条件を指定します。 次のクエリは、名前に "Chef" を含むすべての製品を返します。 また、GetValueOrDefault の使い方にも注目してください。 UnitPrice は null 許容値であるため、Value プロパティを使用して値を取得するか、GetValueOrDefault を呼び出す必要があります。
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()))
文字列が特定の部分文字列で終わるように指定するには、EndsWith メソッドを使用します。
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()))
&& 演算子を使用して、where 句で条件を組み合わせます。
// 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()))
演算子 ?> と ?< は null 許容の演算子です。 null 許容の等価演算子と比較演算子をすべて使用できます。 詳細については、「Linq.NullableOperators モジュール (F#)」を参照してください。
順序付けを指定するには sortBy クエリ演算子を使用し、さらにもう 1 レベル順序付けを指定するには thenBy を使用します。 クエリの select 部分にタプルが使用されている点にも注目してください。 したがって、クエリには要素型としてタプルが含まれています。
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)
skip 演算子を使用して、指定した数のレコードを無視し、take 演算子を使用して、返すレコードの数を指定します。 この方法で、データ フィードにページングを実装できます。
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))
OData 要求の確認
OData のすべてのクエリは、特定の OData 要求 URI に変換されます。 完全なデータ コンテキスト オブジェクトの SendingRequest イベントにイベント ハンドラーを追加することによって、デバッグなどを行うためにその URI を確認できます。
OData 要求を確認するには
OData 要求 URI を確認するには、次のコードを使用します。
// The DataContext property returns the full data context. db.DataContext.SendingRequest.Add (fun eventArgs -> printfn "Requesting %A" eventArgs.Request.RequestUri)
前のコードの出力は次のようになります。
requesting http://services.odata.org/Northwind/Northwind.svc/Orders()?$orderby=ShippedDate&$select=OrderID,ShippedDate