How do you handle continuations in WCF-OData with a URL query?
I am working with a WCF Data Service pointing to an OData endpoint. If I use a DataServiceQuery, I can manage the continuation without any trouble.
var collection = new DataServiceCollection<T>();
collection.LoadCompleted += (sender, e) =>
{
开发者_StackOverflow中文版 if (e.Error != null)
{
callback(null, e.Error);
return;
}
var thisCollection = (DataServiceCollection<T>) sender;
if (thisCollection.Continuation != null)
{
thisCollection.LoadNextPartialSetAsync();
}
else
{
var items = thisCollection.ToList();
callback(items, e.Error);
}
};
collection.LoadAsync(query);
However, I don't see how you can do the same for a DataServiceContext.BeginExecute(string url, ...) method.
_odataContext.BeginExecute<T>(new Uri(requestUrl), x =>
{
var items = _odataContext.EndExecute<T>(x);
//not sure how to get the rest of the items with this method
});
How can I use the url-based query method but still get continuation support?
A synchronous sample (to make it simpler):
var r = ctx.Execute<Product>(new Uri("http://services.odata.org/Northwind/Northwind.svc/Products"));
QueryOperationResponse<Product> response = (QueryOperationResponse<Product>)r;
response.Count();
Console.WriteLine(response.GetContinuation());
In short, the Execute method returns instance of QueryOperationResponse, which implements IEnumerable but also exposes the continuation.
For completeness, here's the full function that follows continuations for URL queries.
public void ExecuteFullQuery<T>(Uri requestUrl, Action<IEnumerable<T>> callback)
{
var list = new List<T>();
ExecuteFullQueryImpl(requestUrl, list, callback);
}
private void ExecuteFullQueryImpl<T>(Uri requestUrl, List<T> items, Action<IEnumerable<T>> callback)
{
_odataContext.BeginExecute<T>(requestUrl, x =>
{
var results = _odataContext.EndExecute<T>(x);
if (results != null)
items.AddRange(results.ToList());
var response = (QueryOperationResponse<T>)results;
var continuation = response.GetContinuation();
if (continuation != null)
{
ExecuteFullQueryImpl(continuation.NextLinkUri, items, callback);
}
else
{
callback(items);
}
},
null);
}
Use a lazy enumerator
public IEnumerable<Product> GetProducts()
{
Uri request = new Uri("http://services.odata.org/Northwind/Northwind.svc/Products");
var response = (QueryOperationResponse<Product>)ctx.Execute<Product>(request);
while (true)
{
foreach (Product p in response)
{
yield return p;
}
var continuation = response.GetContinuation();
if (continuation == null)
{
yield break;
}
response = ctx.Execute(continuation);
}
}
精彩评论