带有 EFCore 的 OData - 为什么没有 WHERE 子句?
OData with EFCore - why no WHERE clause?
我有一段时间没有弄乱 OData,但我记得它真的很有用。所以我为我的 API 选择了 .NetCore 3.1 EFCore + OData 架构。为了让它完全通用等等等等
做一点测试,我可以从我的浏览器中得到预期的结果:例如
https://localhost:44310/things?someidfield=44
很酷,我回来了 JSON 我期待的!但是速度太慢了,为什么呢?查看 SQL(探查器)我可以看到它没有 WHERE 子句,它从数据库中获取所有内容并在内存中过滤,在 50 万条记录上?
我在这里错过了什么?我已经尝试了多种方法来编写 GET 方法。从不传递任何 queryOptions(有效!但下面的结果相同)开始,然后在下面我明确地将选项应用到 EFCore 实体。
[HttpGet]
[EnableQuery]
public async Task<IEnumerable<thing>> GetThingsAsync(ODataQueryOptions<thing> queryOptions)
{
return await queryOptions.ApplyTo(DB.thing).Cast<thing>().ToListAsync();
}
正在将结果集加载到内存中,因为您正在调用 ToListAsync() 并返回一个 IEnumerable。
如果您的 GetThingsAsync 方法 returns 是 IQueryable<T>
(而不是 IEnumerable<T>
),则查询将应用于数据库,并且只会获取过滤后的数据。
如果 DB.thing 是一个 EFCore DbSet(实现 IQueryable<T>
),那么您可以将您的方法简化为
[HttpGet]
[EnableQuery]
public Task GetThingsAsync()
{
return DB.thing;
}
此外,就像已经提到的评论中的某些内容一样,在您的情况下正确的过滤语法是 ?$filter=someidfield eq 44
我有一段时间没有弄乱 OData,但我记得它真的很有用。所以我为我的 API 选择了 .NetCore 3.1 EFCore + OData 架构。为了让它完全通用等等等等
做一点测试,我可以从我的浏览器中得到预期的结果:例如
https://localhost:44310/things?someidfield=44
很酷,我回来了 JSON 我期待的!但是速度太慢了,为什么呢?查看 SQL(探查器)我可以看到它没有 WHERE 子句,它从数据库中获取所有内容并在内存中过滤,在 50 万条记录上?
我在这里错过了什么?我已经尝试了多种方法来编写 GET 方法。从不传递任何 queryOptions(有效!但下面的结果相同)开始,然后在下面我明确地将选项应用到 EFCore 实体。
[HttpGet]
[EnableQuery]
public async Task<IEnumerable<thing>> GetThingsAsync(ODataQueryOptions<thing> queryOptions)
{
return await queryOptions.ApplyTo(DB.thing).Cast<thing>().ToListAsync();
}
正在将结果集加载到内存中,因为您正在调用 ToListAsync() 并返回一个 IEnumerable。
如果您的 GetThingsAsync 方法 returns 是 IQueryable<T>
(而不是 IEnumerable<T>
),则查询将应用于数据库,并且只会获取过滤后的数据。
如果 DB.thing 是一个 EFCore DbSet(实现 IQueryable<T>
),那么您可以将您的方法简化为
[HttpGet]
[EnableQuery]
public Task GetThingsAsync()
{
return DB.thing;
}
此外,就像已经提到的评论中的某些内容一样,在您的情况下正确的过滤语法是 ?$filter=someidfield eq 44