c# - 适用于 ASP.NET Core 和 OData 的 REST Web API 中的 IQueryable、IEnumerable 和异步

标签 c# asp.net-core odata

我正在为一个项目使用 OData 和 Web API。 ASP 中默认生成的 EF Controller 提供如下所示的端点/操作:

// GET: api/Users
[HttpGet]
public async Task<ActionResult<IEnumerable<User>>> GetUsers()
{
    return await _context.Users.ToListAsync();
}

据我所知,这会返回一个 User 对象列表,这些对象被序列化为 JSON 并作为一个大 JSON 数组返回给消费者。它是异步的,允许服务器在 EF 在后台查询数据库时服务其他请求。服务请求的管理由 ASP 和 ControllerBase 类在上游进行。

按照此处的示例:https://learn.microsoft.com/en-gb/shows/on-net/supercharging-your-web-apis-with-odata-and-aspnet-core?wt.mc_id=ondotnet-c9-cephilli ,我只需在 Get 操作上方添加 Queryable 属性即可维护带有 Swagger/OpenAPI 支持的传统 REST API。

但是,这让我思考:这是最佳解决方案吗?如果我有 100 万个用户,但消费者只调用前 100 个用户,那么在 OData 开始查询仅 100 条记录以返回给消费者之前,获取操作是否会等待获取完整的用户 DbSet?我应该以 DbSet 的形式返回 IQueryable 吗?:

// GET: api/Users
[HttpGet]
[EnableQuery]
public ActionResult<IQueryable<User>> GetUsers()
{
    return _context.Users;
}

由于操作不再异步,这是否会改变传统 API 调用或 OData 调用?是否有其他最佳或推荐的解决方案来返回可跨传统 API 和 OData API 运行的查询?

最佳答案

IQueryable 和 IEnumerable 之间存在巨大差异。

IQueryable 是一个允许 LINQ to SQL 的接口(interface),这意味着它将在数据库中运行筛选的查询,而 IEnumerable 是 LINQ to Object,这意味着它在数据库中执行查询,然后在内存中过滤掉。

例如,就您而言

public async Task<ActionResult<IQueryable<User>>> GetUsers()
{
    return await _context.Users;
}

这将从数据库返回所有用户,因此 IQueryable 和 IEnumerable 之间没有太大区别,但正如您提到的,您有 100 万条记录,而您只需要 100 条记录,那么您的查询将变为

public async Task<ActionResult<IQueryable<User>>> GetUsers()
{
    return await _context.Users.Take(100);
}

现在,返回 IEnumerable 将加载要加载到内存中的所有百万条记录,然后为您提供前 100 条记录,而 IQueryable 只会从数据库中获取 100 条记录。

关于c# - 适用于 ASP.NET Core 和 OData 的 REST Web API 中的 IQueryable、IEnumerable 和异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72515393/

相关文章:

c# - 在 Razor Pages 中使用 @functions block 的错误和警告

post - 使用扩展创建 OData POST 实体

asp.net-core - CreateRef 方法迁移到 .Net Core 导致 404,如何使用 .Net Core 在 OData 中实现创建关系

entity-framework - 用于检索派生类型的 OData 查询

c# - 我怎样才能等待 Task.WhenAll( ... ).ContinueWith( AnotherAwaitable )?

asp.net - 如何在.net core框架中使用TransactionScope?我找不到它

asp.net-core - .Net 核心 Ping 类 - System.Net.Ping 或 System.Net.Utilities

c# - 如何编码(marshal)包含可变大小字符串的结构?

c# - 获取给定某一天的一周中的天数范围

c# - .NET String.Length 属性返回什么?代理中性长度或完整字符长度