Entity framework 如果使用$top,则带有EF Core的AutoMapper不会正确返回OData@count
我正在使用此链接提供的解决方案: 我的问题是在使用$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;} } 我的地图: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
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();
}