C# 使用LINQ到实体的外部联接查询
我的公司有0到n个部门,1个部门有0到n个办公室,1个办公室有0到n个员工。现在我需要使用linq查询,按部门列出员工的平均年龄,如果部门中没有人,则默认平均年龄为0。 代码如下:C# 使用LINQ到实体的外部联接查询,c#,linq,entity-framework,linq-to-entities,C#,Linq,Entity Framework,Linq To Entities,我的公司有0到n个部门,1个部门有0到n个办公室,1个办公室有0到n个员工。现在我需要使用linq查询,按部门列出员工的平均年龄,如果部门中没有人,则默认平均年龄为0。 代码如下: DataContext ctx = new DataContext(); var q0 = from d in ctx.Departments join o in ctx.Offices on d.Id equals o.DepartmentId
DataContext ctx = new DataContext();
var q0 = from d in ctx.Departments
join o in ctx.Offices on d.Id equals o.DepartmentId
join e in ctx.Employees on o.Id equals e.OfficeId
group e by d into de
select new {
DepartmentId = de.Key.Id,
AverageAge = de.Count() == 0 ? 0 : de.Average(e => e.Age),
};
var q1 = from d in ctx.Departments
join de in q0 on d.Id equals de.DepartmentId into des
from de in des.DefaultIfEmpty()
select new
{
DepartmentName = d.Name,
AverageAge = de == null ? 0 : de.AverageAge
};
var result = q1.ToList();
foreach (var item in result)
{
Console.WriteLine("{0}-{1}", item.DepartmentName, item.AverageAge);
}
ctx.Dispose();
但是如何将q0和q1组合到一个查询中呢
were you meaning something along the lines of:
var newQ2 = from d in ctx.Departments
outer left join o in ctx.Offices on d.Id equals o.DepartmentId
outer left join e in ctx.Employees on o.Id equals e.OfficeId
group e by d into de
select new {
DepartmentId = de.Key.Id,
AverageAge = de.Count() == 0 ? 0 : de.Average(e => e.Age),
};
改为:
var newQ2 = from d in ctx.Departments
join o in ctx.Offices on d.Id equals o.DepartmentId
join e in ctx.Employees on o.Id equals e.OfficeId
group e by d into de.DefaultIfEmpty()
select new {
DepartmentId = de.Key.Id,
DepartdentName = select d.Name from d where d.id = de.Key.Id,
AverageAge = de.Count() == 0 ? 0 : de.Average(e => e.Age),
};
附录:我会使用子选择来匹配额外的名称,不知道我从代码中临时制作的db布局,但您可以使其更有效,并基于子选择进行多部分连接。抱歉,我无法在工作中测试此代码,我可以很好地估计,但如果您需要更详细的答案,则需要有关您的部门名称所在位置的更多信息:我已将左外连接更改回连接,抱歉,我忘记了在c和linq中,您可以使用DefaultIfEmpty在代码中导致左外连接行为
外部左联接将在没有相应值的情况下返回null,但将允许在具有相应值的任何部分上返回。但是Join不会返回任何空条目,我怀疑这就是为什么会有这两个查询
对于我提出的查询,唯一需要注意的是,如果值为null,则在使用它们之前,您需要填充所需的任何值。例如,如果DE为null,DepartmentId将需要一些逻辑来填充它。谢谢大家,我已经得到了答案:
var q1 =
from d in ctx.Departments
from o in ctx.Offices.Where(o => o.DepartmentId == d.Id).DefaultIfEmpty()
from e in ctx.Employees.Where(e => e.OfficeId == o.Id).DefaultIfEmpty()
group e by d into de
select new {
DepartmentName = de.Key.Name,
AverageAge = de.Average(e => e == null ? 0 : e.Age),
};
这是一篇关于使用LINQ:Perfect extension进行连接的好文章。但是它们是方法,不是流畅的LINQ。我认为您可以进一步修改这篇文章,以引入名称部分,然后我相信OPs第二个查询是不必要的。外部左连接是一个很好的解决方案。但是它不是有效的LINQ语法,如果语法有效,这三个单词将以蓝色作为c关键字。