使用 WCF OData 和 GetContinuation() 方法进行服务器端分页
我正在使用 QueryOperationResponse GetContinuation() 方法尝试对从 odata wcf feed 读取的非常大的数据集进行分页。我正在使用一些从微软获得的 OData 帮助程序库。
问题是分页过程似乎陷入了无限循环,永远不会结束。例如,如果我将页面大小设置为 10000 条记录,并且有 80000 条记录要检索,我会观察到循环会继续进行超过 8 次迭代,而此时它应该完成。
下面是查询服务并实现分页的类(在底部)。我还观察到 NextLinkUri 的“OriginalString”在每次迭代中都不会改变,我认为这是错误的?希望我只是错过了一些非常明显的东西,我认为这是正确的分页方式:
private static IList<dynamic> Get(string serviceUri, NameValueCollection queryOptions, IAuthenticationScheme authenticationScheme)
{
string baseUri;
string entitySet;
string entityKey;
string queryString;
ValidateServiceUri(serviceUri, out baseUri, out entitySet, out entityKey, out queryString);
string resource = !string.IsNullOrEmpty(entityKey) ? entitySet + "(" + entityKey + ")" : entitySet;
DataServiceContext context = new DataServiceContext(new Uri(baseUri));
context.IgnoreMissingProperties = true;
DataServiceContextHandler handler = new DataServiceContextHandler(authenticationScheme);
handler.HandleGet(context);
DataServiceQuery<EntryProxyObject> query = context.CreateQuery<EntryProxyObject>(resource);
NameValueCollection options = HttpUtility.ParseQueryString(queryString);
options.Add(queryOptions);
foreach (string key in options.AllKeys)
{
query = query.AddQueryOption(key, options[key]);
}
QueryOperationResponse<EntryProxyObject> response = query.Execute() as QueryOperationResponse<EntryProxyObject>;
IList<dynamic> result;
if (options["$inlinecount"] == "allpages")
{
result = new DynamicEntityCollection(response.TotalCount) as IList<dynamic>;
}
else
{
result = new List<dynamic>();
}
foreach (EntryProxyObject proxy in response)
{
DynamicEntity entity = new DynamicEntity(proxy.Properties);
result.Add(entity);
}
while (response.GetContinuation() != null)
{
DataServiceQueryContinuation<EntryProxyObject> continuation = response.GetContinuation();
QueryOperationResponse<EntryProxyObject> nextResponse = context.Execute<EntryProxyObject>(continuation);
Console.WriteLine("Uri: " + continuation.NextLinkUri.OriginalString);
foreach (EntryProxyObject proxy in nextResponse)
{
DynamicEntity entity = new DynamicEntity(proxy.Properties);
result.Add(entity);
}
}
return result;
}
这就是我调用该方法的方式:
return OData.Get("http://xxx.x.xxx.xx/MyDataService.svc/MyProducts", "$filter=Index gt 0");
I am using the QueryOperationResponse GetContinuation() method to attempt and page through a very large data set read off an odata wcf feed. I am using some OData helper libraries acquired from microsoft.
The problem is that the paging process seems to get stuck in an infinite loop, and never finishes. For example if I set the page size to 10000 records and there are 80000 records to retrieve, I observe that the loop continues for well over 8 iterations, when it should be finished.
Below is the class that queries the service and implements the paging (at the bottom). I also observed that the 'OriginalString' of the NextLinkUri never changes with each iteration, which I think is wrong? Hopefully I'm just missing something really obvious, I think this is the correct way to page:
private static IList<dynamic> Get(string serviceUri, NameValueCollection queryOptions, IAuthenticationScheme authenticationScheme)
{
string baseUri;
string entitySet;
string entityKey;
string queryString;
ValidateServiceUri(serviceUri, out baseUri, out entitySet, out entityKey, out queryString);
string resource = !string.IsNullOrEmpty(entityKey) ? entitySet + "(" + entityKey + ")" : entitySet;
DataServiceContext context = new DataServiceContext(new Uri(baseUri));
context.IgnoreMissingProperties = true;
DataServiceContextHandler handler = new DataServiceContextHandler(authenticationScheme);
handler.HandleGet(context);
DataServiceQuery<EntryProxyObject> query = context.CreateQuery<EntryProxyObject>(resource);
NameValueCollection options = HttpUtility.ParseQueryString(queryString);
options.Add(queryOptions);
foreach (string key in options.AllKeys)
{
query = query.AddQueryOption(key, options[key]);
}
QueryOperationResponse<EntryProxyObject> response = query.Execute() as QueryOperationResponse<EntryProxyObject>;
IList<dynamic> result;
if (options["$inlinecount"] == "allpages")
{
result = new DynamicEntityCollection(response.TotalCount) as IList<dynamic>;
}
else
{
result = new List<dynamic>();
}
foreach (EntryProxyObject proxy in response)
{
DynamicEntity entity = new DynamicEntity(proxy.Properties);
result.Add(entity);
}
while (response.GetContinuation() != null)
{
DataServiceQueryContinuation<EntryProxyObject> continuation = response.GetContinuation();
QueryOperationResponse<EntryProxyObject> nextResponse = context.Execute<EntryProxyObject>(continuation);
Console.WriteLine("Uri: " + continuation.NextLinkUri.OriginalString);
foreach (EntryProxyObject proxy in nextResponse)
{
DynamicEntity entity = new DynamicEntity(proxy.Properties);
result.Add(entity);
}
}
return result;
}
This is how I call the method:
return OData.Get("http://xxx.x.xxx.xx/MyDataService.svc/MyProducts", "$filter=Index gt 0");
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你总是在关注第一个响应的延续。这保持不变(出于显而易见的原因)。您需要查看代码中 nextResponse 的延续,以确定是否还有更多数据需要读取,并获取延续以获取下一页。上面的代码读取第一页,然后一遍又一遍地读取第二页。
You are always looking at the continuation of the first response. That stays constant (for obvious reasons). You need to look at the continuation of the nextResponse in your code to figure out if there's more data to read and to get the continuation to get the next page. The code above reads the first page and then reads the second page over and over again.