我正在玩一个项目周围玩一个项目。 ASP中的默认生成的EF控制器给出了端点/操作,看起来像:
// GET: api/Users
[HttpGet]
public async Task<ActionResult<IEnumerable<User>>> GetUsers()
{
return await _context.Users.ToListAsync();
}
从我可以收集的内容中,这返回了一个用户对象列表,这些用户对象被序列化为JSON并返回消费者作为一个大JSON数组。在EF查询后台数据库时,允许服务器可以提供其他请求是异步的。服务请求的管理发生由ASP和ControllerBase类上游。
在此处之后: https://learn.microsoft.com/en-gb/shows/on-net/net/net/supercharging-your-web-apis-web-apis-with-with-with-with-odata-indata-indata-andaet -core?wt.mc_id = ondotnet-c9-cephilli ,我可以通过简单地在上方添加可查询> Queryable
属性来维护常规的rest api w/swagger/openapi支持 get> get> get /代码>操作。
但是,这让我思考:这是最佳解决方案吗?如果我有100万用户,但是消费者只会命名前100名,那么在ODATA开始向其询问其仅100个记录才能返回消费者之前,该动作是否会等待。我是否应该以DBSET的形式返回可观的
// GET: api/Users
[HttpGet]
[EnableQuery]
public ActionResult<IQueryable<User>> GetUsers()
{
return _context.Users;
}
?是否还有其他一些最佳或推荐解决方案用于返回在常规和ODATA API中起作用的查询?
I'm playing around w/ OData and Web API for a project. The default generated EF controller in ASP gives endpoints/actions that look like :
// 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. It is async to allow the server to serve other requests while EF queries the database in the background. The management of serving requests happens upstream by ASP and the ControllerBase class.
Following the example here: https://learn.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.
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? Should I be returning an IQueryable in the form of the DbSet?:
// 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? Is there some other optimal or recommended solution for returning queries that works across both conventional and OData APIs?
发布评论
评论(2)
令人难以置信的和iEnumerable之间存在巨大差异。
Iqueryable是一个允许LINQ到SQL的接口,这意味着它将在数据库中运行过滤的查询运行,而IEnumerable则是Linq to Object objoct,这意味着它在数据库中执行查询,然后在内存中过滤出来。
例如,在您的情况下,
将返回数据库中的所有用户
这 加载所有要加载在内存中的数百万个记录,然后给您前100个记录,而Iqueryable只能从数据库中获得100个。
There is a massive difference between IQueryable and 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.
For example, In your case
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
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.
是的,您应该返回
iQueryable
将您的ODATA查询转换为数据库查询:因为支持
iqueryable
(和ef core)被烘烤到odata中,所以我会假设您的操作仍然是异步的,区别在于,TolistAsync
的调用现在由ODATA库来处理类似的方法。Yes, you should return an
IQueryable
to translate your OData query into a database query:https://learn.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 toToListAsync
and similar methods are now handled by the OData library.