遅延コンテンツの読み込み (WCF Data Services)

WCF Data Services の既定では、クエリが返すデータの量が制限されます。 その一方で、関連エンティティ、ページングされた応答データ、およびバイナリ データ ストリームを含む追加データをデータ サービスから必要に応じて明示的に読み込むことが可能です。 このトピックでは、このような遅延コンテンツをアプリケーションに読み込む方法について説明します。

関連エンティティ

クエリを実行すると、アドレス指定したエンティティ セット内のエンティティだけが返されます。 たとえば、Northwind データ サービスに対するクエリが Customers エンティティを返す場合、CustomersOrders の間にリレーションシップがあっても、既定では関連 Orders エンティティは返されません。 また、データ サービスでページングが有効になった場合は、以降のデータ ページをサービスから明示的に読み込む必要があります。 関連エンティティを読み込むには、2 つの方法があります。

  • 一括読み込み: $expand クエリ オプションを使用して、クエリが要求するエンティティ セットへのアソシエーションによって関連付けられたエンティティをクエリが返すよう要求できます。 DataServiceQuery に対して Expand メソッドを使用して、データ サービスに送信されるクエリに $expand オプションを追加します。 次の例に示すように、エンティティ セットをコンマで区切ることによって関連する複数のエンティティ セットを要求できます。 クエリによって要求されたすべてのエンティティは、1 つの応答で返されます。 次の例では、Order_Details および CustomersOrders エンティティ セットと一緒に返されます。

    ' Define a query for orders that also returns items and customers.
    Dim query As DataServiceQuery(Of Order) = _
    context.Orders.Expand("Order_Details,Customer")
    
    // Define a query for orders that also returns items and customers.
    DataServiceQuery<Order> query =
        context.Orders.Expand("Order_Details,Customer");
    

    WCF Data Services は、$expand クエリ オプションを使用して、1 つのクエリに含めることができるエンティティ セットの数を 12 に制限しています。

  • 明示的読み込み: DataServiceContext インスタンスで LoadProperty メソッドを呼び出して、関連エンティティを明示的に読み込むことができます。 LoadProperty メソッドへの各呼び出しによって、データ サービスへの個別の要求が作成されます。 次の例では、Orders エンティティの Order_Details を明示的に読み込みます。

    ' Explicitly load the order details for each order.
    context.LoadProperty(order, "Order_Details")
    
    // Explicitly load the order details for each order.
    context.LoadProperty(order, "Order_Details");
    

どちらのオプションを使用するかを検討する場合、データ サービスへの要求の数と 1 つの応答で返されるデータの量のバランスを考慮してください。 アプリケーションが関連オブジェクトを必要とし、それらのオブジェクトを明示的に取得するための追加要求による待機時間を回避する場合は、一括読み込みを使用します。 しかし、アプリケーションが特定の関連エンティティ インスタンスのデータしか必要としない場合は、LoadProperty メソッドを呼び出して、これらのエンティティを明示的に読み込むことを検討することをお勧めします。 詳細については、「方法: 関連エンティティを読み込む (WCF Data Services)」を参照してください。

ページングされたコンテンツ

データ サービスでページングが有効化されている場合、データ サービスが返すフィード内のエントリの数はデータ サービスの構成によって制限されます。 ページ制限は、各エンティティ セットに対して個別に設定できます。 詳細については、「データ サービスの構成 (WCF Data Services)」を参照してください。 ページングが有効である場合、フィードの最終的なエントリには、データの次のページへのリンクが含まれます。 このリンクは、DataServiceQueryContinuation オブジェクトに含まれます。 データの次のページへの URI は、DataServiceQuery が実行されたときに返される QueryOperationResponseGetContinuation メソッドを呼び出すことによって取得します。 返された DataServiceQueryContinuation オブジェクトが使用されて、結果の次のページが読み込まれます。 クエリ結果は、GetContinuation メソッドを呼び出す前に列挙する必要があります。 最初に do…while ループを使用してクエリ結果を列挙した後に、次の non-null リンク値をチェックすることをお勧めします。 GetContinuation メソッドが null (Visual Basic の場合は Nothing) を返す場合、元のクエリに追加の結果ページはありません。 次の例は、Northwind サンプル データ サービスからページングされた顧客データを読み込む docwhile ループを示します。

' With a paged response from the service, use a do...while loop 
' to enumerate the results before getting the next link.
Do
    ' Write the page number.
    Console.WriteLine("Page {0}:", pageCount + 1)

    ' If nextLink is not null, then there is a new page to load.
    If token IsNot Nothing Then
        ' Load the new page from the next link URI.
        response = CType(context.Execute(Of Customer)(token),  _
        QueryOperationResponse(Of Customer))
    End If

    ' Enumerate the customers in the response.
    For Each customer As Customer In response
        Console.WriteLine("\tCustomer Name: {0}", customer.CompanyName)
    Next

    ' Get the next link, and continue while there is a next link.
    token = response.GetContinuation()
Loop While token IsNot Nothing
// With a paged response from the service, use a do...while loop 
// to enumerate the results before getting the next link.
do
{
    // Write the page number.
    Console.WriteLine("Page {0}:", pageCount++);

    // If nextLink is not null, then there is a new page to load.
    if (token != null)
    {
        // Load the new page from the next link URI.
        response = context.Execute<Customer>(token)
            as QueryOperationResponse<Customer>;
    }

    // Enumerate the customers in the response.
    foreach (Customer customer in response)
    {
        Console.WriteLine("\tCustomer Name: {0}", customer.CompanyName);
    }
}

// Get the next link, and continue while there is a next link.
while ((token = response.GetContinuation()) != null);

要求されたエンティティ セットと一緒に関連エンティティを 1 つの応答で返すようクエリが要求すると、ページング制限は、応答と共にインラインで含まれるネストされたフィードに影響することがあります。 たとえば、Northwind サンプル データ サービスで Customers エンティティ セットに対してページング制限が設定されている場合、次の Northwind サンプル データ サービスを定義する Northwind.svc.cs ファイルの例に示すように、独立したページング制限を関連 Orders エンティティ セットに設定することもできます。

' Set page size defaults for the data service.
config.SetEntitySetPageSize("Orders", 20)
config.SetEntitySetPageSize("Order_Details", 50)
config.SetEntitySetPageSize("Products", 50)

' Paging requires v2 of the OData protocol.
config.DataServiceBehavior.MaxProtocolVersion = _
    System.Data.Services.Common.DataServiceProtocolVersion.V2
// Set page size defaults for the data service.
config.SetEntitySetPageSize("Orders", 20);
config.SetEntitySetPageSize("Order_Details", 50);
config.SetEntitySetPageSize("Products", 50);

// Paging requires v2 of the OData protocol.
config.DataServiceBehavior.MaxProtocolVersion =
    System.Data.Services.Common.DataServiceProtocolVersion.V2;

この場合、最上位レベルの Customers エンティティ フィードとネストされた Orders エンティティ フィードの両方にページングを実装する必要があります。 次の例は、選択した Customers エンティティに関連する Orders エンティティのページを読み込むために使用する while ループを示します。

While nextOrdersLink IsNot Nothing
    For Each o As Order In c.Orders
        ' Print out the orders.
        Console.WriteLine("\t\tOrderID: {0} - Freight: ${1}", _
                o.OrderID, o.Freight)
    Next
    ' Load the next page of Orders.
    Dim ordersResponse = _
    context.LoadProperty(c, "Orders", nextOrdersLink)
    nextOrdersLink = ordersResponse.GetContinuation()
End While
while (nextOrdersLink != null)
{
    foreach (Order o in c.Orders)
    {
        // Print out the orders.
        Console.WriteLine("\t\tOrderID: {0} - Freight: ${1}",
            o.OrderID, o.Freight);
    }

    // Load the next page of Orders.
    var ordersResponse = context.LoadProperty(c, "Orders", nextOrdersLink);
    nextOrdersLink = ordersResponse.GetContinuation();
}

詳細については、「方法: ページングされた結果を読み込む (WCF Data Services)」を参照してください。

バイナリ データ ストリーム

WCF Data Services では、バイナリ ラージ オブジェクト (BLOB) データにデータ ストリームとしてアクセスできます。 ストリーミングは必要になるまでバイナリ データの読み込みを待機し、クライアントは、このデータを効率的に処理できます。 この機能を活用するには、データ サービスは IDataServiceStreamProvider プロバイダーを実装する必要があります。 詳細については、「ストリーミング プロバイダー (WCF Data Services)」を参照してください。 ストリーミングが有効である場合、エンティティ型は関連バイナリ データなしで返されます。 この場合、サービスのバイナリ データのデータ ストリームにアクセスするには、DataServiceContext クラスの GetReadStream メソッドを使用する必要があります。 同様に、SetSaveStream メソッドを使用して、エンティティのバイナリ データをストリームとして追加または変更します。 詳細については、「バイナリ データの操作 (WCF Data Services)」を参照してください。

参照

概念

データ サービスのクエリ (WCF Data Services)

その他のリソース

WCF Data Services クライアント ライブラリ