假设 OData 和实体框架可以很好地协同工作,因为 OData 选项将被传递到 EF db 上下文以过滤查询 - 即。仅返回从服务器请求的记录数,以免增加有效负载,而不是过滤所有记录。
给定以下 URL 路径:
/api/Users?$top=10&$skip=10
给定以下控制器操作:
[Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
public IEnumerable<USER> Get(ODataQueryOptions<USER> options)
{
var dbContext = new ATMS.DAL.AtmsContext();
//var ret = options.ApplyTo(dbContext.USERS).Cast<USER>().ToArray(); // returns 10 rows but client sees 0
var ret = dbContext.USERS.ToArray(); // returns all records, filtered results to client
return ret;
}
使用时ret = options.ApplyTo(dbContext.USERS).Cast<USER>().ToArray();
,从 SQL Server Profiler 我看到执行了适当的查询,并通过实体框架从数据库返回了 10 个结果。
由 10 项组成的数组返回,ret
但问题是对客户端的响应中不包含任何数据:
{
"odata.metadata":"http://localhost:59337/api/$metadata#Users","value":[
]
}
如果没有指定跳过,则返回前 10 个结果——显然对分页没有用处。
当使用ret = dbContext.USERS.ToArray();
前 10 个结果时,skip 被正确应用,但这只是因为所有的结果都是从数据库返回的,并且随后应用了过滤,这不是我想要实现的。
在我的 WebApiConfig.cs 中,我有config.EnableQuerySupport();
.
添加PageSize
属性没有效果:
[Queryable(AllowedQueryOptions = AllowedQueryOptions.All, PageSize = 10)]
返回IQueryable<User>
也没有效果。
返回PageResult<USER>
- 没有变化:
IQueryable results = options.ApplyTo(dbContext.USERS.AsQueryable(), settings);
return new PageResult<USER>(
results as IEnumerable<USER>,
Request.GetNextPageLink(),
Request.GetInlineCount());
- 更多信息 -
使用/api/Users?$top=10&$skip=0
,如果我在操作方法的开头设置断点并在 Visual Studio 中调试时设置 Skip.RawValue 并继续执行,我会得到预期的 10 个结果:
似乎不知何故,结果会受到额外的跳过,这可能是没有显示结果的原因。
使用时http://localhost:59337/api/Users?$top=10&$skip=9
,显示第 2 页的倒数第二个结果 - 只有一个结果。
我缺少什么才能使其正常工作,还有其他人经历过吗?