연습: 형식 공급자를 사용하여 OData 서비스에 액세스(F#)
OData(개방형 데이터 프로토콜)는 인터넷을 통해 데이터를 전송하는 프로토콜입니다.많은 데이터 공급자가 OData 웹 서비스를 게시하여 데이터에 대한 액세스를 허용하고 있습니다.ODataService 형식 공급자에 의해 자동으로 생성된 데이터 형식을 사용하는 F# 3.0에서 모든 OData 소스의 데이터에 액세스할 수 있습니다.OData에 대한 자세한 내용은 Introducing OData를 참조하십시오.
이 연습에서는 F# ODataService 형식 공급자를 사용하여 서비스를 제공하는 OData 서비스 및 쿼리 데이터 피드에 대한 클라이언트 형식을 만드는 방법을 보여줍니다.
이 연습에서는 다음 작업을 보여 줍니다. 이 경우 연습을 성공적으로 수행하기 위해 이 순서대로 수행해야 합니다.
Configuring a client project for an OData service
Accessing OData types
Querying an OData service
Verifying the OData requests
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 서비스에 쿼리하는 방법
이제 형식 공급자를 설정하여 OData 서비스를 쿼리할 수 있습니다.
OData는 사용할 수 있는 쿼리 작업의 하위 집합만 지원합니다.다음 작업 및 해당 키워드가 지원됩니다.
프로젝션 (select)
필터링(where, 문자열 및 날짜 연산 사용)
페이징 (skip, take)
순서 지정 (orderBy, thenBy)
OData 특정 작업인 AddQueryOption 및 Expand입니다
자세한 내용은 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)
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 메서드를 사용하여 부분 문자열 조건을 쿼리에 지정합니다.다음 쿼리는 이름에서 "요리사"와 모든 제품을 반환합니다.또한 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 쿼리 연산자를 사용하여 순서를 지정하고 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)
스킵 연산자를 사용하여 지정된 레코드 수를 무시하고, 반환할 레코드 수를 지정하기 위하여 테이크 연산자를 사용합니다.이 방식으로 데이터 피드에서 페이징을 구현할 수 있습니다.
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 요청