Entity framework 如果使用$top,则带有EF Core的AutoMapper不会正确返回OData@count

Entity framework 如果使用$top,则带有EF Core的AutoMapper不会正确返回OData@count,entity-framework,.net-core,odata,automapper,Entity Framework,.net Core,Odata,Automapper,我正在使用此链接提供的解决方案: 我的问题是在使用$top时,@odata.count始终返回$top中通知的数字,但应返回总记录数 我知道ODataQueryOptions有一个属性“Count”,但我不知道是否可以使用它来解决这个问题 我使用的代码如下所示,该代码由БМааааааааааааааа 有以下实体: 公共课教材目录{ 公共字符串名称{get;set;} public int?ImageId{get;set;} 公共虚拟映像映像{get;set;} 公共虚拟ICollection

我正在使用此链接提供的解决方案:

我的问题是在使用$top时,@odata.count始终返回$top中通知的数字,但应返回总记录数

我知道ODataQueryOptions有一个属性“Count”,但我不知道是否可以使用它来解决这个问题

我使用的代码如下所示,该代码由БМааааааааааааааа

有以下实体:

公共课教材目录{ 公共字符串名称{get;set;} public int?ImageId{get;set;} 公共虚拟映像映像{get;set;} 公共虚拟ICollection课程{get;set;} } 公共课{ 公共字符串名称{get;set;} 公共字符串说明{get;set;} public int?ImageId{get;set;} 公共虚拟映像映像{get;set;} public int LessonCatalogId{get;set;} 公共虚拟LessonCatalog LessonCatalog{get;set;} } 意见: 公共课LessonView{ 公共字符串名称{get;set;} 公共字符串说明{get;set;} public int?ImageId{get;set;} 公共图像视图图像{get;set;} public int LessonCatalogId{get;set;} 公共LessonCatalogView LessonCatalog{get;set;} } 公共课LessonCatalogView{ 公共字符串名称{get;set;} public int?ImageId{get;set;} 公共图像视图图像{get;set;} 公共IEnumerable课程{get;set;} } 我的地图:

CreateMap<LessonCatalog, LessonCatalogView>()
            .ForMember(dest => dest.Image, map => map.ExplicitExpansion())
            .ForMember(dest => dest.Lessons, map => map.ExplicitExpansion());

CreateMap<Lesson, LessonView>()
             .ForMember(dest => dest.LessonCatalog, map => map.ExplicitExpansion());
In my repository:

protected readonly DbContext _context;
protected readonly DbSet<TEntity> _entities;

    public Repository(DbContext context) {
        _context = context;
        _entities = context.Set<TEntity>();
    }

public IEnumerable<TView> GetOData<TView>(ODataQueryOptions<TView> query,
        Expression<Func<TEntity, bool>> predicate = null) {

        IQueryable<TEntity> repQuery = _entities.AsQueryable();
        IQueryable res;
        if (predicate != null) repQuery = _entities.Where(predicate);

        if (query != null) {
            string[] expandProperties = GetExpands(query);
            //!!!
            res = repQuery.ProjectTo<TView>(Mapper.Configuration, null, expandProperties);
            //!!!
            var settings = new ODataQuerySettings();
            var ofilter = query.Filter;
            var orderBy = query.OrderBy;
            var skip = query.Skip;
            var top = query.Top;

            if (ofilter != null) res = ofilter.ApplyTo(res, settings);
            if (orderBy != null) res = orderBy.ApplyTo(res, settings);
            if (skip != null) res = skip.ApplyTo(res, settings);
            if (top != null) res = top.ApplyTo(res, settings);
        } else {
            res = repQuery.ProjectTo<TView>(Mapper.Configuration);
        }

        return (res as IQueryable<TView>).AsEnumerable();
    }
计数的结果应为

"@odata.count": 1007
但结果总是如此

"@odata.count": 5

使用SQL Server概要文件,我可以看到Select for count包含“top”。那么,如何避免这种情况发生呢?

感谢@Gennady Pundikov,我从Github的人那里得到了帮助,现在可以回答这个问题了

我更改了GetOData方法以在应用其他设置之前获取计数:

public IEnumerable<TView> GetOData<TView>(ODataQueryOptions<TView> query,
        Expression<Func<TEntity, bool>> predicate = null) {

        IQueryable<TEntity> repQuery = _entities.AsQueryable();
        IQueryable res;
        if (predicate != null) repQuery = _entities.Where(predicate);

        if (query != null) {
            string[] expandProperties = GetExpands(query);
            //!!!
            res = repQuery.ProjectTo<TView>(Mapper.Configuration, null, expandProperties);
            //!!!
            var settings = new ODataQuerySettings();
            var ofilter = query.Filter;
            var orderBy = query.OrderBy;
            var skip = query.Skip;
            var top = query.Top;

            if (ofilter != null) res = ofilter.ApplyTo(res, settings);
            if (query.Count?.Value == true)
            {
                // We should calculate TotalCount only with filter
                // http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part2-url-conventions.html#_Toc371341773
                // 4.8 Addressing the Count of a Collection
                // "The returned count MUST NOT be affected by $top, $skip, $orderby, or $expand.
                query.Request.ODataFeature().TotalCount = ((IQueryable<TView>)res).LongCount();
            }

            if (top != null) res = top.ApplyTo(res, settings);
            if (orderBy != null) res = orderBy.ApplyTo(res, settings);
            if (skip != null) res = skip.ApplyTo(res, settings);
        } else {
            res = repQuery.ProjectTo<TView>(Mapper.Configuration);
        }

        return (res as IQueryable<TView>).AsEnumerable();
    }

感谢@Gennady Pundikov,我得到了Github人的帮助,现在我可以回答这个问题了

我更改了GetOData方法以在应用其他设置之前获取计数:

public IEnumerable<TView> GetOData<TView>(ODataQueryOptions<TView> query,
        Expression<Func<TEntity, bool>> predicate = null) {

        IQueryable<TEntity> repQuery = _entities.AsQueryable();
        IQueryable res;
        if (predicate != null) repQuery = _entities.Where(predicate);

        if (query != null) {
            string[] expandProperties = GetExpands(query);
            //!!!
            res = repQuery.ProjectTo<TView>(Mapper.Configuration, null, expandProperties);
            //!!!
            var settings = new ODataQuerySettings();
            var ofilter = query.Filter;
            var orderBy = query.OrderBy;
            var skip = query.Skip;
            var top = query.Top;

            if (ofilter != null) res = ofilter.ApplyTo(res, settings);
            if (query.Count?.Value == true)
            {
                // We should calculate TotalCount only with filter
                // http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part2-url-conventions.html#_Toc371341773
                // 4.8 Addressing the Count of a Collection
                // "The returned count MUST NOT be affected by $top, $skip, $orderby, or $expand.
                query.Request.ODataFeature().TotalCount = ((IQueryable<TView>)res).LongCount();
            }

            if (top != null) res = top.ApplyTo(res, settings);
            if (orderBy != null) res = orderBy.ApplyTo(res, settings);
            if (skip != null) res = skip.ApplyTo(res, settings);
        } else {
            res = repQuery.ProjectTo<TView>(Mapper.Configuration);
        }

        return (res as IQueryable<TView>).AsEnumerable();
    }