如何在 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 中引用这些新名称。您不必重命名 DepartmentId
和 ObjectHeadId
,因为它们已经不同,但我发现它使代码比混合重命名和未重命名更整洁:
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
顺便说一句,
我需要加入三个实体,我需要从中对一列求和,并且列的名称在两个实体中相同。在 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 中引用这些新名称。您不必重命名 DepartmentId
和 ObjectHeadId
,因为它们已经不同,但我发现它使代码比混合重命名和未重命名更整洁:
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
顺便说一句,