如何在 EF Core 中按具有相同名称的不同实体的多个列进行分组 - C#

How to group by multiple column with same name of different entity in EF Core - C#

我需要加入三个实体,我需要从中对一列求和,并且列的名称在两个实体中相同。在 sql 中,我可以使用以下查询来实现此目的

select 
     a.ObjectHeadId,
     a.DepartmentId, 
     b.Name as ObjectHeadName,
     c.Name as DepartmentName,
     SUM(BudgetEstimate) 
 from ConsolidatedAppendix1s a
 inner join ObjectHeads b on b.ObjectHeadId=a.ObjectHeadId
 inner join Departments c on a.DepartmentId=c.DepartmentId
 group by a.ObjectHeadId, a.DepartmentId, b.Name, c.Name

在 EF Core 中尝试相同时,我正在这样做

               consolidatedAppendixI = await _context.ConsolidatedAppendix1s
                                      .Include(entity => entity.Department)
                                      .Include(entity => entity.ObjectHead)
               .GroupBy(r => new {
                   r.Department.Name,
                   r.DepartmentId,
                   r.ObjectHeadId,
                   r.ObjectHead.Name
               })
               .Select(a => new 
               {
                   ObjectHeadId = a.Key.ObjectHeadId,
                   DepartmentId=a.Key.DepartmentId
                   BudgetEstimate = a.Sum(r => r.BudgetEstimate),
                   ObjectHeadName= a.Key.Name,
                   DepartmentName = a.Key.Name,

               }).ToListAsync(cancellationToken);

这样做会显示 匿名类型不能有多个同名属性

我可以使用

实现这个
GroupBy(x=> 1)

但这里的问题是我无法在选择时获得 Key 中的其他列,同样它是在上面为 ObjectHeadId、ObjectHeadName 等完成的

这是因为分组依据中的名称相同,即使它们是不同实体的 属性。如何对这些列进行分组以获得总和或 sql 等效的 linq 查询?

给属性取不同的名字;它与您在 SQL SELECT 块中使用 AS 的方式基本相同:

new {
  DeptName =  r.Department.Name,
  DeptId =    r.DepartmentId,     //optional rename
  HeadId =    r.ObjectHeadId,     //optional rename
  HeadName =  r.ObjectHead.Name
})

并在 Select 中引用这些新名称。您不必重命名 DepartmentIdObjectHeadId,因为它们已经不同,但我发现它使代码比混合重命名和未重命名更整洁:

new {
  DeptName =  r.Department.Name,
  r.DepartmentId,     
  r.ObjectHeadId,    
  HeadName =  r.ObjectHead.Name
})

您当然可以根据自己的喜好自由选择这条路线!


如果在创建匿名类型时没有指定 属性 名称(通过在 = 的左侧写一个名称),编译器将根据名称推断一个您正在使用其值的 属性。因为您有两个名称为 Name 的属性(在不同的对象上),编译器基本上会尝试创建一个匿名类型,如下所示:

var x = new {
  Name = thing1.Name,
  Name = thing2.Name
}

当然,这行不通,因为如果你说 var y = x.Name 不清楚你在说哪个 Name


顺便说一句,