【问题标题】:How to limit the amount of data from an OData request?如何限制来自 OData 请求的数据量?
【发布时间】:2013-08-09 05:13:49
【问题描述】:

我有一个包含 76 个用户的用户表和用户组表。

使用 MVC、OData、通用存储库和 EF,我尝试在基于用户组进行过滤时优化数据检索:

/api/Users?$filter=USERGROUPS/any(usergroup: usergroup/ID eq 'Group1')

在客户端,我得到了正确的用户数 - 71(因为 OData 正在根据结果进行过滤),但是我想限制从实际查询返回的记录数 - 即。我不想返回所有记录然后过滤(对于非常大的数据集不是最佳的)。

我的API控制器方法如下:

    [Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
    public IQueryable<USER> Get()
    {
        var unitOfWork = new ATMS.Repository.UnitOfWork(_dbContext);

        var users = unitOfWork.Repository<USER>()
                              .Query()
                              .Include(u => u.USERGROUPS)
                              .Get()
                              .OrderBy(order => order.USERNAME);

        unitOfWork.Save();      // includes Dispose()

        return users.AsQueryable();
    }

我在this post 中读到:

实体框架负责构建基于 请求。

但是,使用 SQL Server 分析器,执行的查询是请求所有记录,而不是过滤查询。

向查询添加 .Take() 并不能达到预期的结果,因为我们还需要返回的实际记录数用于分页。

我正在考虑使用通过 ODataQueryOptions 抓取一些属性,但这似乎也不太正确。

我对工作单元和存储库的实施是否不正确,与我要完成的工作有关,如果是,如何纠正?

【问题讨论】:

    标签: asp.net-mvc asp.net-web-api entity-framework-5 odata


    【解决方案1】:

    简单 - 只需为 Queryable 属性设置页面大小 [Queryable(PageSize=10)]

    http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options#server-paging

    如果您告诉 EF 在哪里应用这些选项,它会起作用。 像这样:

        //[Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
        public IQueryable<USER> Get(ODataQueryOptions<USER> options)
        {
    
            var users = options.ApplyTo(_dbContext.Set<USER>()
                                  .Query()
                                  .Include(u => u.USERGROUPS)
                                  .Get()
                                  .OrderBy(order => order.USERNAME));
    
            return users;
        }
    

    您的代码不起作用,因为它试图将选项应用到最后一行“users.AsQueryable()”,所以实际发生的是 EF 拉取 FULL 数据集,然后将查询应用到最后一行行(这是一个内存集合)。这就是为什么您没有看到“过滤器”没有被传递给 SQL。

    机制是这样的,EF 尝试将 Query 应用于它在代码中找到的 IQueryable 集合(仍然存在一个问题,它如何找到正确的行)。

    【讨论】:

    • 我看到了它是如何工作的以及为下一组数据提供的 url,但是,在查看 SQL Profiler 时,所有请求都是针对所有数据的。也许如果有人可以解释这个机制,以及如何不返回所有数据然后过滤?
    • 好的,但是对于您发布的代码,options.ApplyTo() 括号内的代码存在问题:参数类型 'System.Linq.IOrderedEnumerable' 是不可分配给参数类型“System.Linq.IQueryable”。添加 .AsQueryable);在 OrderBy 结束时修复它,但返回类型仍然不正确。
    • 除此之外,假设我们只从数据库返回 10 条记录,是否有后续调用或部分调用来检索记录总数?
    • 嗯,这有点答案 - 你的问题就是你的解决方案的答案:) 你只能将过滤器应用于 Iqueryable 集合。这是 IEnumerable 和 Iqueryable 之间的主要思想和主要区别。
    • 如果你可以使用返回 IQueryable 的 DBContext 中的 smth - 你会没事的。如果你使用 Ienumerable 作为源,所有可以做的就是过滤内存中的数据集。
    猜你喜欢
    • 1970-01-01
    • 2012-12-31
    • 2016-11-18
    • 1970-01-01
    • 2021-02-20
    • 2021-11-12
    • 1970-01-01
    • 2020-04-26
    • 2022-07-08
    相关资源
    最近更新 更多