共用方式為


逐步解說:使用型別提供者存取 OData 服務 (F#)

OData (指 Open Data Protocol,開放式資料通訊協定) 是透過網際網路傳輸資料的通訊協定。許多資料提供者會發行 OData Web 服務讓他們的資料可以公開供他人存取。您可以從任何 OData 來源的資料在 F# 3.0 使用由 ODataService 型別提供者所產生的資料型別。如需 Introducing OData 的詳細資訊,請參閱 GDI+。

這個逐步解說會示範如何使用 ODataService F# 型別的提供者產生 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創造一組型別。兩個物件有包含有關資料的資訊,一個是簡化的資料內容,在db 的範例中。這個物件只包含與資料庫相關,其中包括資料表或摘要型別的資料型別。其他物件,如下列範例所 fullContext ,是 DataContext 的執行個體並且包含許多其他屬性、方法和事件。

查詢 OData 服務

在這個步驟中,您使用 F# 查詢運算式查詢 OData 服務。

查詢 OData 服務

  1. 現在您已經設定了型別提供者,您可以查詢 OData 服務。

    OData 只支援可用查詢作業的子集。支援下列作業和其對應的關鍵字:

    • 投影(select)

    • 篩選 (where,透過使用字串和日期作業)。

    • 分頁 (skip, take)

    • 排序 (orderBy, thenBy)

    • AddQueryOption 和 Expand,是 OData 特定的作業

    如需詳細資訊,請參閱LINQ Considerations

    如果您需要摘要或資料表中的所有項目,請使用查詢運算式最簡單的形式,如下列程式碼所示:

    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)
    
  2. 您可以使用在 SELECT 關鍵字之後的tuple來指定您想要欄位或資料行。

    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)
    
  3. 您可以使用 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))                         
    
  4. 您可以使用Contains 方法來指定子字串條件查詢。下列查詢會回傳具有「Cook」在其名稱的所有產品。同時也請注意使用 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()))
    
  5. 使用 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()))
    
  6. 您可以使用 && 運算子來合併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#)

  7. 使用 sortBy 查詢運算子來指定順序,和使用 thenBy 指定另一個層級的排序。同時記得使用在查詢的選取部分的 tuple。因此,查詢中具有 tuple 做為元素型別。

    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)
    
  8. 您可以使用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)
    

    上述程式碼的輸出是:

要求 http://services.odata.org/Northwind/Northwind.svc/ Orders()? $orderby=ShippedDate&$select=OrderID ShippedDate,

請參閱

工作

查詢運算式 (F#)

參考

ODataService 型別提供者 (F#)

其他資源

LINQ Considerations