t.b*_*art 6 c# asynchronous entity-framework odata asp.net-web-api
我一直在四处寻找这个问题的答案,但我似乎无法找到任何明确的答案.我们使用OData v4,使用ODataQueryOptions.ApplyTo将OData选项应用于查询.我们还使用ODataQuerySettings来设置pagesize.当我们设置页面大小时,我们不能再使用从ODataQueryOptions.ApplyTo返回的IQueryable上的ToListAsync().错误消息表明IQueryable的提供程序不再来自Entity Framework.
我发现这是因为在使用pagesize时,OData通过传递TruncatedCollection来解析IQueryable.此TruncatedCollection 从数据库中检索所有(pagesize + 1)结果,以检查是否有多于pagesize的结果.但是,ApplyTo不是异步方法,因此我可以安全地假设此数据库查询不是异步执行的.
我能做些什么来确保查询是异步执行的吗?当然OData团队已经想到了这个?或者它是否可以保持同步?对我来说,现在似乎异步IO几乎是必需的,因为我们希望我们的API能够很好地扩展,并且在等待IO时不会阻止所有线程.
谢谢您的帮助!
编辑1:
我被要求提供一些代码来解释我的意思.
在BaseController.cs中:
public class BaseController : ODataController
{
    private static readonly ODataQuerySettings DefaultSettings = new ODataQuerySettings() { PageSize = 60 };
    protected Task<IHttpActionResult> ODataResult<T>(IQueryable<T> query, ODataQueryOptions<T> options)
    {
        IQueryable result = options.ApplyTo(query, DefaultSettings);
        return Task.FromResult(ODataOk(result));
    }
}
在CustomerController.cs中:
public class CustomerController : BaseController
{
    ICustomerService customerService;
    public async Task<IHttpActionResult> Get(ODataQueryOptions<Customer> options)
    {
        var query = customerService.Query();
        return await ODataResult(query, options);
    }
}
正如我上面所说,问题出在ApplyTo的底层代码中.这是OData本身的一种方法.这条线:
    IQueryable result = options.ApplyTo(query, DefaultSettings);
已经执行了数据库查询,因为我们在DefaultSettings中定义了一个pagesize.定义pagesize会导致ApplyTo中的底层代码从数据库中检索所有数据,然后将检索到的列表作为可查询返回.这意味着在同步函数中查询数据库.
所以,我的问题是:有没有办法在不放弃异步读取的情况下实现对OData的分页?或者在尝试这样做时我是否过于复杂?
Tim*_*ers -2
我不知道你为什么要打电话ToListAsync()。应该没有必要。在您的操作方法中,您应该编写查询,但实际上不获取任何数据。所有这些都应该是微不足道的,不需要异步。IQueryable稍后由框架执行。(框架还应自动将查询字符串中的所有 OData 筛选器参数应用到您返回的查询,包括分页)。
事实上,拥有类型的异步结果IQueryable(或IEnumerable就此而言)是没有意义的(请参阅此答案)。您无法异步枚举。
理论上,您可以将所有结果异步获取到数组中,但随后 Odata 会在内存中应用其过滤器,而不是针对查询。我不知道为什么你需要这样做,但是使用 Odata 就没有什么意义了。
| 归档时间: | 
 | 
| 查看次数: | 3553 次 | 
| 最近记录: |