使用数据访问层时支持 OData 计数

Supporting OData Count when using Data Access Layer

我的 ASP.NET5 API 站点使用数据访问层(管理器、服务、存储等)从数据库中提取数据。这些层从控制器和 return IActionResult 调用到调用者。这些层允许我们向执行的查询添加业务规则和其他“后端”逻辑。

添加 ASP.NET OData 后,一切正常 除了 $count 参数。这是因为,在正常情况下,IQueryable<T> 是从控制器 return 编辑的,它允许 OData 根据传入的查询参数修改查询并执行它。此执行包括(最有可能)不添加 $skip$top 的查询的第二次执行,因此总行数可以包含在结果集中。

但是,因为我的 DAL 正在 returning 一个 IEnumerable<T>(在查询 已经 执行之后),OData 服务(??ActionFilter? ?) 根据给定的集合生成 不准确的 计数。

请注意,我在控制器中使用 ODataQueryOptions<T> 来排除 filter、skip 和 top 参数,以便它们可以向下传递到不同的数据访问层。

public class MyController : ControllerBase {

   [EnableQuery()]
   public async Task<IActionResult> GetMyStuff(ODataQueryOptions<Stuff> options) {
      // Extract filter, skip, top from ODataQueryOptions

      var x = await _manager.GetStuff(filter, skip, top);

      var count = await _manager.GetCountOfStuff(filter);
      // How do I let OData know what the count value is???

      return Ok(x);
   }

}
}

假设我生成计数值(使用我的 DAL),我的问题最终变成了

我怎样才能让 OData 知道 这个值是什么,而不是 试图找出它?

这是我自己想出来的。不确定它是什么时候添加的(我不记得几年前我第一次开始使用 MS OData 库时看到过这个)但是 Request 对象中有一个名为 ODataFeature() 的扩展方法,它允许您设置一些响应值。

我的代码最终看起来像

public class MyController : ControllerBase {

   [EnableQuery()]
   public async Task<IActionResult> GetMyStuff(ODataQueryOptions<Stuff> options) {
      // Extract filter, skip, top from ODataQueryOptions

      var x = await _manager.GetStuff(filter, skip, top);

      // ****************************************************
      // NEW code to optional inject $count when needed

      if (options.Count?.Value == true) {
         Request.ODataFeature().TotalCount = await _manager.GetCountOfStuff(filter);
      }

      // ****************************************************

      return Ok(x);
   }

}