简体   繁体   English

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

[英]IQueryable, IEnumerable and async in REST Web API for ASP.NET Core and OData

I'm playing around w/ OData and Web API for a project.我正在为一个项目使用 OData 和 Web API。 The default generated EF controller in ASP gives endpoints/actions that look like : ASP 中默认生成的 EF 控制器提供如下所示的端点/操作:

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

From what i can gather, this returns a list of User objects that are serialized into JSON and returned to the consumer as a big JSON array.据我所知,这将返回一个用户对象列表,这些对象被序列化为 JSON 并作为一个大的 JSON 数组返回给消费者。 It is async to allow the server to serve other requests while EF queries the database in the background.当 EF 在后台查询数据库时,允许服务器处理其他请求是异步的。 The management of serving requests happens upstream by ASP and the ControllerBase class.服务请求的管理由 ASP 和 ControllerBase 类在上游进行。

Following the example here: https://docs.microsoft.com/en-gb/shows/on-net/supercharging-your-web-apis-with-odata-and-aspnet-core?wt.mc_id=ondotnet-c9-cephilli , I can maintain a conventional REST API w/ Swagger/OpenAPI support by simply adding a Queryable attribute above the Get action.按照此处的示例: https ://docs.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。

However, this got me thinking: is this the optimal solution?然而,这让我思考:这是最佳解决方案吗? If I have 1 million users, but the consumer is only calling a Top 100, will the Get Action wait to get the full Users DbSet before OData starts to query it for only 100 records to return to the consumer?如果我有 100 万用户,但消费者只调用前 100 个用户,那么在 OData 开始查询它以仅返回 100 条记录返回给消费者之前,获取操作是否会等待获取完整的用户 DbSet? Should I be returning an IQueryable in the form of the DbSet?:我应该以 DbSet 的形式返回 IQueryable 吗?:

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

Will this change either conventional API calls or OData calls now that the Action is no longer async?现在 Action 不再是异步的,这是否会改变传统的 API 调用或 OData 调用? Is there some other optimal or recommended solution for returning queries that works across both conventional and OData APIs?是否有其他一些最佳或推荐的解决方案来返回适用于传统 API 和 OData API 的查询?

There is a massive difference between IQueryable and IEnumerable. IQueryable 和 IEnumerable 之间存在巨大差异。

IQueryable is an interface that allows LINQ to SQL meaning that it will run filtered query runs in the database whereas IEnumerable is LINQ to Object meaning it executes the query in the database, then filters out in the memory. IQueryable 是一个允许 LINQ to SQL 的接口,这意味着它将运行在数据库中运行的过滤查询,而 IEnumerable 是 LINQ to Object,这意味着它在数据库中执行查询,然后在内存中过滤。

For example, In your case例如,在您的情况下

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

this will return all users from the database so not much of a difference between IQueryable and IEnumerable, but as you mentioned you have 1 million records and you need only 100 records, then your query becomes这将返回数据库中的所有用户,所以 IQueryable 和 IEnumerable 之间没有太大区别,但是正如你提到的,你有 100 万条记录,你只需要 100 条记录,那么你的查询就变成了

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

Now, returning IEnumerable will load all of your million records to be loaded in memory and then give you the top 100, whereas IQueryable will get you only 100 from the database.现在,返回 IEnumerable 将加载所有要加载到内存中的百万条记录,然后为您提供前 100 条记录,而 IQueryable 只会从数据库中获取 100 条记录。

Yes, you should return an IQueryable to translate your OData query into a database query:是的,您应该返回一个IQueryable以将您的 OData 查询转换为数据库查询:

Returning System.Linq.IQueryable or ActionResult enables OData to translate queries to SQL queries using ef core capabilities.返回 System.Linq.IQueryable 或 ActionResult 使 OData 能够使用 ef 核心功能将查询转换为 SQL 查询。 Returning other types such as IEnumerable causes OData to perform queries in the app.返回其他类型(例如 IEnumerable)会导致 OData 在应用程序中执行查询。

https://docs.microsoft.com/en-us/odata/webapi/first-odata-api#update-the-controller https://docs.microsoft.com/en-us/odata/webapi/first-odata-api#update-the-controller

Since support for IQueryable (and ef core) is baked into OData I would assume your action is still async, the difference is that the calls to ToListAsync and similar methods are now handled by the OData library.由于对IQueryable (和 ef 核心)的支持已融入 OData,因此我假设您的操作仍然是异步的,不同之处在于对ToListAsync和类似方法的调用现在由 OData 库处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ASP.NET中的oData,REST和Web API - oData, REST and Web API in asp.net 创建在ASP.NET Core Web API中返回OData的enbdpoints - Creating enbdpoints that return OData in ASP.NET Core Web API ASP.Net MVC4 RC Web-Api Odata过滤器不能与IQueryable一起使用 - ASP.Net MVC4 RC Web-Api Odata filter not working with IQueryable 在ASP.NET MVC 5中可查询到IEnumerable - IQueryable to IEnumerable in ASP.NET MVC 5 ASP.NET 内核 Web API:异步任务有问题? - ASP.NET Core Web API: having trouble with async task? asp.net 内核中的异步等待 web api(不是 MVC) - async-await in asp.net core web api (not MVC) 在 ASP.NET Core Web 应用程序中使用 REST API - Consuming REST API in ASP.NET Core web application 将参数传递给ASP.NET的Web API 2 OData v4 REST API - Passing parameters to ASP.NET's Web API 2 OData v4 REST API 如何在asp net core web API上正确地将列表转换为IQueryable - How to properly convert a list to IQueryable on a asp net core web API 抛出异常的 IEnumerable 在 ASP.NET 核心 Web ZDB93474238D1043CACE1 中的 OkResult 传递时返回无效的 Json - IEnumerable that throws exception returns invalid Json when passed into OkResult in ASP.NET Core Web API
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM