使用数据访问层时支持 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);
}
}
我的 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);
}
}