.net core EF Core 3.18从相关表中获取总和和计数

.net core EF Core 3.18从相关表中获取总和和计数,.net-core,lambda,entity-framework-core,.net Core,Lambda,Entity Framework Core,我有一个web api,我试图在其中获取相关表的总和和计数。使用.net core 3和EF core 3.1.8。 这就是我尝试过的: \u context.Books .包括(r=>r.BookCategories) .Include(r=>r.Resources) .Include(r=>r.Ratings.GroupBy(g=>g.Bookid)。选择(s=>new{sumalldoves=s.Sum(item=>item.Rating)})) .ToListAsync(); 但我刚刚

我有一个web api,我试图在其中获取相关表的总和和计数。使用.net core 3和EF core 3.1.8。 这就是我尝试过的:

\u context.Books
.包括(r=>r.BookCategories)
.Include(r=>r.Resources)
.Include(r=>r.Ratings.GroupBy(g=>g.Bookid)。选择(s=>new{sumalldoves=s.Sum(item=>item.Rating)}))
.ToListAsync();
但我刚刚收到一条错误消息。(见下文)。 我发现使用EF Core进行调试很困难,因为我不知道哪里出了问题。我已经尝试了几个小时,但无论我写什么,我都会收到相同的错误消息。 我想也许你们能看出哪里出了问题

我想要什么

我试图得到表内所有评级的总和。 评级仅包含0或1。我试图对每一本书的评级进行汇总。我想把它放在这个类中
public int sumalldows{get;set;}
。 因为我列出了所有的书…其中一个属性就是SumAllVotes。(当我完成这个问题时,还有CountAllVoces)。 到最后,我将有一个SumallVoces和CountalVoces,并可以计算出有多少人按“1”的百分比

错误消息:

处理请求时发生未处理的异常。 InvalidOperationException:包含中使用的Lambda表达式为 无效。 Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpansionExpressionVisitor.ProcessInclude(NavigationExpansionExpression 源代码、表达式、布尔值(包括)

我尝试过的:

[HttpGet]
公共异步任务GetBooks()
{
Guid userid=Guid.Parse(this.User.FindFirst(ClaimTypes.NameIdentifier).Value);
返回等待上下文
.包括(r=>r.BookCategories)
.Include(r=>r.Resources)
.Include(r=>r.Ratings.GroupBy(g=>g.Bookid)。选择(s=>new{sumalldoves=s.Sum(item=>item.Rating)}))
.ToListAsync();
}           
账簿和评级的定义如下:-

公共部分类书
{
公共书籍()
{
Bookmarks=newhashset();
注释=新的HashSet();
Favorites=新HashSet();
BookCategories=newhashset();
Resources=newhashset();
评级=新的HashSet();
}
公共int Id{get;set;}
公共字符串标题{get;set;}
公共字符串说明{get;set;}
公共字节Scaleoffun{get;set;}
公共字节标量{get;set;}
公共int?目标{get;set;}
公共int?第二个目标{get;set;}
公共int?Thirdgoal{get;set;}
公共int?主体ID{get;set;}
公共int?Categoryid{get;set;}
公共字符串语言{get;set;}
公共字符串估计时间{get;set;}
公共字符串图像{get;set;}
公共int?文件{get;set;}
public int?Ownerid{get;set;}
public DateTime Createdon{get;set;}
公共日期时间?Lastmodifiedon{get;set;}
公共字符串活动{get;set;}
公共字符串Url{get;set;}
公共Guid用户标识{get;set;}
公共字节?等级{get;set;}
[未映射]
公共整数总和投票{get;set;}
[未映射]
公共int countallvoces{get;set;}
公共虚拟类别类别{get;set;}
公共虚拟课程目标导航{get;set;}
公共虚拟用户所有者{get;set;}
公共虚拟课程第二目标导航{get;set;}
公共虚拟主题主题{get;set;}
公共虚拟课程第三航空{get;set;}
公共虚拟ICollection书签{get;set;}
公共虚拟ICollection注释{get;set;}
公共虚拟ICollection收藏夹{get;set;}
公共虚拟ICollection图书类别{get;set;}
公共虚拟ICollection资源{get;set;}
公共虚拟ICollection分级{get;set;}
}
公共部分类评级
{
公共int Id{get;set;}
public int?Bookid{get;set;}
公共字符串类型{get;set;}
公共Int16?评级{get;set;}
公共Guid用户标识{get;set;}
公共字符串主题{get;set;}
public DateTime Createdon{get;set;}
公共日期时间?Modifiedon{get;set;}
公共字节?活动{get;set;}
公共虚拟图书{get;set;}
//公共虚拟用户用户{get;set;}
}    
以下是我尝试过的一些其他解决方案,但得到了相同的错误消息:

.Include(r=>r.Ratings.Sum(i=>i.Rating))

.Include(r=>new{m=r.Ratings.GroupBy(g=>g.Bookid)})

您不需要按父实体的Id对子实体进行分组。当您
包含一对多子实体时,它们将被添加到父实体的子实体列表中,并因此根据它们之间的关系按父实体的标识进行分组。您所需要做的就是告诉EF您希望从子列表中得到什么值

将您的查询更改为-

\u context.Books
.包括(r=>r.BookCategories)
.Include(r=>r.Resources)
.包括(r=>r.评级)
.选择(p=>new
{
//设置Books实体中的所有基元属性
Id=p.Id,
标题=p.标题,
//等等。。。
//设置计算属性
CountAllVoces=p.Ratings.Count,
sumalldowes=p.Ratings.Sum(x=>x.Rating)
//设置相关实体
BookCategories=p.BookCategories,
资源=p.资源
})
.ToListAsync();

具有一个
ProjectTo
方法,该方法生成所需的查询并自动执行投影(选择
部分)。您可以使用它来避免手动设置所有这些属性的麻烦。

我建议您不要将Include与Select一起使用。阅读如何使用投影进行查询(选择)。注意,Rating.Rating是可以为空的,您需要处理这个问题。下面是一个可能的代码sa
var view = await _context.Books
.Where(your condition)
.Select(item => new
{
     //Todo: fill other props
     SumAllVotes = item.Ratings.Sum(rating => (Int16?) rating.Rating),
     CountAllVotes = item.Ratings.Count,
 })
 .ToListAsync()