0

假设 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 页的倒数第二个结果 - 只有一个结果。

我缺少什么才能使其正常工作,还有其他人经历过吗?

4

1 回答 1

1

你不要混搭QueryableAttributeand ODataQueryOptions<T>。根据您是要手动控制应用查询选项 ( ODataQueryOptions<T>) 还是自动执行 ( QueryableAttribute) 来选择一个。

你有两个选择,

public IEnumerable<USER> Get(ODataQueryOptions<USER> options)
{
    var dbContext = new ATMS.DAL.AtmsContext();
    var ret = options.ApplyTo(dbContext.USERS).Cast<USER>();
    return ret;
}

或者

[Queryable]
public IEnumerable<USER> Get(ODataQueryOptions<USER> options)
{
    var dbContext = new ATMS.DAL.AtmsContext();
    var ret = dbContext.USERS;
    return ret;
}

您看到该行为的原因是您应用了两次查询,一次使用ODataQueryOptions<T>.ApplyTo,然后再次通过QueryableAttribute.

于 2013-08-08T19:17:50.223 回答