Query Continuations for nested collections in Data Services

Or - why are there a number of overloaded GetContinuation methods on QueryOperationResponse?

This is part three on server paging in ADO.NET Data Services - see also parts one and two.

There are three GetContinuation methods. One takes no arguments, another takes an IEnumerable<T> and the other takes an IEnumerable. Conceptually there are only two: one with no arguments and another one with an enumerable parameter. Each act on different data, as will soon become obvious.

The no-argument method returns the continuation result for the next page for the query you just executed. The 'T' in the result is the 'T' of the query you execute, as you're getting more elements from that collection.

The one-argument methods return the continuation for the next page on the collection you're passing in. The 'T' of the result (if you use the generic form) is the 'T' of the passed-in collection, as you're getting more elements for the collection, not the original query.

An example should help to clairify. Let's say that I run this query:

var q = from c in context.Customers
        select new Customer() {
          ID = c.ID,
          Orders = c.Orders.ToList()
        };

This query is asking for the ID and orders of every customer. For this example, the server might choose to return no more than three customers per collection, and no more than three orders per collection.

This means that the response will have the first three customers, and each of those customers will have at most three orders expanded, possibly with a link to the rest of the customer's orders.

Here is where the GetContinuation distinction comes in. If you invoke the GetContinuation overload with no arguments, you'll get the continuation object for the following three customers. If you invoke the GetContinuation overload with the Orders collection of the first customer, you'll get the continuation object for the rest of the orders of the first customer. Once you realize that the enumeration represents one collection, it becomes obvious that you'll be getting the continuation for that collection, and nothing else. You can keep getting continuations from the response of this continuation, and so on.

The query response internally keeps track of which enumeration is associated with which continuation from the payload, so make sure you get the continuation before throwing that query response away.

Enjoy!