Loading Deferred Content (ADO.NET Data Services)

By default, ADO.NET Data Services limits the amount of data that a query returns. However, you can explicitly load additional data, including related entities, paged response data, and binary data streams, from the data service when it is needed. This topic describes how to load such deferred content into your application.

When you execute a query, only entities in the addressed entity set are returned. For example, when a query against the Northwind data service returns Customers entities, by default the related Orders entities are not returned, even though there is a relationship between Customers and Orders. Also, when paging is enabled in the data service, you must explicitly load subsequent data pages from the service. There are two ways to load related entities:

  • Eager loading: You can use the $expand query option to request that the query return entities that are related by an association to the entity set that the query requested. You can request multiple related entity sets by separating them by a comma, as in the following example. All entities requested by the query are returned in a single response. The following example returns Order_Details and Customers together with the Orders entity set:

    ' Define a query for orders that also returns items and customers.
    Dim query As DataServiceQuery(Of Orders) = _
    context.Orders.Expand("Order_Details,Customers")
    
    // Define a query for orders that also returns items and customers.
    DataServiceQuery<Orders> query =
        context.Orders.Expand("Order_Details,Customers");
    
  • Explicit loading: You can call the LoadProperty(Object, String) method on the DataServiceContext instance to explicitly load related entities. Each call to the LoadProperty(Object, String) method creates a separate request to the data service. The following example explicitly loads Order_Details for an Orders entity:

    ' 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");
    

When you consider which option to use, realize that there is a tradeoff between the number of requests to the data service and the amount of data that is returned in a single response. Use eager loading when your application requires associated objects and you want to avoid the added latency of additional requests to explicitly retrieve them. However, if there are cases when the application only needs the data for specific related entity instances, you should consider explicitly loading those entities by calling the LoadProperty(Object, String) method. For more information, see How to: Load Related Entities (ADO.NET Data Services).

Paged Content

When paging is enabled in the data service, the number of entries in the feed that the data service returns is limited by the configuration of the data service. Page limits can be set separately for each entity set. For more information, see Configuring the Data Service (ADO.NET Data Services). When paging is enabled, the final entry in the feed contains a link to the next page of data. This link is contained in a DataServiceQueryContinuation object. You obtain the URI to the next page of data by calling the GetContinuation() method on the QueryOperationResponse returned when the DataServiceQuery is executed. The returned DataServiceQueryContinuation object is then used to load the next page of results. You must enumerate the query result before you call the GetContinuation() method. Consider using a do…while loop to first enumerate the query result and then check for a non-null next link value. When the GetContinuation() method returns null (Nothing in Visual Basic), there are no additional result pages for the original query. The following example shows a do…while loop that loads paged customer data from the Northwind sample data service.

' 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 Customers)(token),  _
        QueryOperationResponse(Of Customers))
    End If

    ' Enumerate the customers in the response.
    For Each customer As Customers 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<Customers>(token)
            as QueryOperationResponse<Customers>;
    }

    // Enumerate the customers in the response.
    foreach (Customers 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);

When a query requests that related entities are returned in a single response together with the requested entity set, paging limits may affect nested feeds that are included inline with the response. For example, when a paging limit is set in the Northwind sample data service for the Customers entity set, an independent paging limit can also be set for the related Orders entity set, as in the following example from the Northwind.svc.cs file that defines the Northwind sample data service.

config.SetEntitySetPageSize("Customers", 10)
config.SetEntitySetPageSize("Orders", 5)

config.DataServiceBehavior.MaxProtocolVersion = _
    System.Data.Services.Common.DataServiceProtocolVersion.V2
config.SetEntitySetPageSize("Customers", 8);
config.SetEntitySetPageSize("Orders", 5);

config.DataServiceBehavior.MaxProtocolVersion =
    System.Data.Services.Common.DataServiceProtocolVersion.V2;

In this case, you must implement paging for both the top-level Customers and the nested Orders entity feeds. The following example shows the while loop used to load pages of Orders entities related to a selected Customers entity.

While nextOrdersLink IsNot Nothing
    For Each o As Orders 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 (Orders 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();
}

For more information, see How to: Load Paged Results (ADO.NET Data Services).

Binary Data Streams

ADO.NET Data Services enables you to access binary large object (BLOB) data as a data stream. Streaming defers the loading of binary data until it is needed, and the client can more efficiently process this data. In order to take advantage of this functionality, the data service must implement the IDataServiceStreamProvider provider. For more information, see Data Services Providers (ADO.NET Data Services). When streaming is enabled, entity types with binary properties are returned without the binary data. Use the GetReadStream(Object) method of the DataServiceContext class to access the data stream for the binary data from the service. Similarly, use the SetSaveStream(Object, Stream, Boolean, DataServiceRequestArgs) method to add or change binary data for an entity as a stream.

See Also

Other Resources

Using a Data Service in a .NET Framework Application (ADO.NET Data Services)

Querying the Data Service (ADO.NET Data Services)