【问题标题】:How do you handle continuations in WCF-OData with a URL query?您如何使用 URL 查询处理 WCF-OData 中的延续?
【发布时间】:2014-06-02 22:53:31
【问题描述】:

我正在使用指向 OData 端点的 WCF 数据服务。如果我使用 DataServiceQuery,我可以毫无困难地管理延续。

var collection = new DataServiceCollection<T>();
collection.LoadCompleted += (sender, e) =>
    {
        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);

但是,我不明白如何对 DataServiceContext.BeginExecute(string url, ...) 方法执行相同的操作。

_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
});

我怎样才能使用基于 url 的查询方法,但仍然获得延续支持?

【问题讨论】:

    标签: .net wcf odata


    【解决方案1】:

    一个同步样本(为了更简单):

    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());
    

    简而言之,Execute 方法返回 QueryOperationResponse 的实例,它实现了 IEnumerable,但也暴露了 continuation。

    【讨论】:

      【解决方案2】:

      为了完整起见,下面是 URL 查询延续之后的完整函数。

      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);
      }
      

      【讨论】:

      • 另一种方法是两个方法都返回 IEnumerable 并使用 yield return 来实现,而不是将所有元素加载到持有者列表中。所以当数据量很大时,懒惰更好。
      【解决方案3】:

      使用惰性枚举器

      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);
          }
      }
      

      【讨论】:

      • 您缺少实体的定义。
      • @Lester :您的回答简短而优雅。点赞!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-27
      • 1970-01-01
      • 2012-03-24
      • 1970-01-01
      • 1970-01-01
      • 2012-09-12
      • 2020-09-15
      相关资源
      最近更新 更多