【问题标题】:is OData IQueryable async?OData IQueryable 是异步的吗?
【发布时间】:2019-06-25 21:52:26
【问题描述】:

我正在开发一个 OData 端点以从数据库中返回项目列表。

我返回一个IQueryable 并让前端通过 odata 查询选项处理查询/过滤/扩展/分页。

考虑以下方法:

[ODataRoute]
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
public IActionResult Get() {
    return Ok(context.Vendors.AsQueryable());
}

我知道async 并不是真正需要的,因为这里没有具体化查询。

在这种情况下,查询何时具体化?

它是以异步方式完成的吗?

【问题讨论】:

  • 一个方法只有在异步时才是异步的。当访问端点时,查询物化(在中间件中),因此异步确实很重要。
  • 对,在每个 odata rest api 示例中,我发现这是调用它的正确方法。但是,我们建立了一个小型测试营地,并且有大约 30 个并发用户报告了速度缓慢,cpu 和内存使用量飙升......我想知道这些 API 调用是否是原因,我的理论是资源没有被正确释放,不断堆积......
  • 这些是不同的问题。 async/await 仅有助于线程管理,以便线程不会阻塞 IO 调用。 Async/Await 对内存/资源/cpu 使用没有影响。如果资源没有被释放,那么您需要检查您是如何注册实现 IDisposable 的类型并确保它们不会留下来的。例如,DbContext 类型应注册为InstancePerLifetimeScope(如果您使用扩展名,则为默认值)。
  • 但是,如果您在测试环境和数据库中分析您的应用程序以了解实际发生的情况,您会取得更大的进步。
  • 是的,我会这样做并回帖!

标签: c# asp.net-core entity-framework-core odata


【解决方案1】:

您问了几个问题,我会尽力回答所有问题并澄清一些问题。

我知道异步并不是真正需要的

从不真正需要异步,问题是异步是否有利于您的应用程序。例如,当对 DbContext 进行调用时,有一些网络操作需要时间,如果在此期间不使用异步,线程将等待响应,而不是返回线程池来处理其他请求。

所以是的,它不是必需的,但它可能很有用。

在这种情况下,查询何时具体化?

当访问端点时查询被物化(在中间件中),

是否以异步方式完成?

不,当您传递 Queryable 时,您只是将执行推迟到稍后,这仍然是同步完成的,您需要使用 async/await 模式才能异步执行某些操作

【讨论】:

    【解决方案2】:

    您的查询将在序列化期间具体化。当您的方法被访问时,为了以 JSON 格式返回响应,序列化程序会尝试序列化结果。此时,您的查询实际上会命中数据库并返回结果。 由于没有应用过滤器并且您的查询试图从数据库中检索所有记录,因此应用程序可能会很慢。

    【讨论】:

    • 至少,我所有的前端调用都包含一个像这样的过滤器:?$filter=contains(description, '${term}')。不幸的是,我只需要一个 Id 和 Description 来过滤掉它们。我们确实创建了一些索引,看起来搜索执行得更好。我只是想从后端清除任何不必要的额外开销,以及我对异步和 IQueryable 的任何误解
    • 通常在描述等长文本字段上建立索引并不是一个好主意。您可以尝试的一件事是从客户端强制分页。或者将最大记录限制为一个固定数字,比如 100。用户需要再次查询才能获得下一个 100。在现实世界的场景中,我看不到用户在不滚动或更改的情况下一次查看超过 20 30 条记录的场景一个页面。
    • 场景是预先输入的,我们还包括一个 $top=10
    • 可能你对服务器的调用太频繁了。通常在发送查询之前等待几毫秒并听听用户是否正在按下任何其他键是一个好主意。当用户完成输入时,发送一次查询。不是每次按键。
    猜你喜欢
    • 2019-04-24
    • 2013-04-25
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-26
    • 2012-02-27
    相关资源
    最近更新 更多