GroupBy实体框架核心中查找表的第一个结果



我正在尝试获取志愿者在某个日期范围内每个部分的总工作人日。有一个考勤表,其中包括要映射到成员表的日期和成员id。还有一个节表可以列出所有节,作为成员的member-to-section表可以位于多个节中。

我想按成员所在的第一个部分进行分组,然后统计该部分的所有出席天数。

以下内容非常适用于我在成员表上按1对多字段(类别)分组的情况,但我不知道如何将其更改为第一个部分(如果成员有一个部分)

var result = await _context.Attendance
.Where(p => p.Day >= firstDayOfLastQuarter && p.Day <= lastDayOfLastQuarter)
.GroupBy(p => p.Member.Category.Name)
.Select(p => new { key = p.Key, count = p.Count() })
.ToListAsync();

我在找类似的东西

var result = await _context.Attendance
.Where(p => p.Day >= firstDayOfLastQuarter && p.Day <= lastDayOfLastQuarter && p.Member.MemberToSection.Any(s => s.MemberId == p.MemberId))
.GroupBy(p => p.Member.MemberToSection.First().Section.Name)
.Select(p => new { key = p.Key, count = p.Count() })
.ToListAsync();

更新

产生所需结果的T-Sql代码是

SELECT Count(*) as Total, Section.Name
FROM Attendance
LEFT JOIN Member on Attendance.Member_Id = Member.Id
OUTER APPLY (
SELECT TOP(1) sec.id, sec.Name
FROM MemberToSection m2s
LEFT JOIN Section sec ON m2s.Section_Id = sec.Id
WHERE m2s.Member_Id = Member.Id 
) as Section
WHERE Attendance.Day >= '2016-10-01' AND Attendance.Day <= '2016-12-31'
GROUP BY Section.Name

"类似"代码返回错误

An unhandled exception occurred while processing the request.
ArgumentException: Property 'System.String Name' is not defined for type 'Microsoft.EntityFrameworkCore.Storage.ValueBuffer'

类别

根据要求,这里是相关类别

出席.cs

public partial class Attendance
{
public long Pk { get; set; }
public int MemberId { get; set; }
public DateTime Day { get; set; }
public virtual Member Member { get; set; }
}

成员.cs

public partial class Member
{
public Member()
{
MemberToSection = new HashSet<MemberToSection>();
}
public int Id { get; set; }
public int? CategoryId { get; set; }
public virtual ICollection<MemberToSection> MemberToSection { get; set; }
}

MemberToSection.cs

public partial class MemberToSection
{
public int SectionId { get; set; }
public int MemberId { get; set; }
public virtual Member Member { get; set; }
public virtual Section Section { get; set; }
}

第.cs节

public partial class Section
{
public Section()
{
MemberToSection = new HashSet<MemberToSection>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<MemberToSection> MemberToSection { get; set; }
}

(当前合并的)EF文档以Compare EF Core&EF6.x部分,其中包含非常"有用"的主题"哪一个适合你"。看来英孚核心还不适合你。以下内容适用于目前最新的EF Core v1.0。

首先,GroupBy(即使是简单的基元属性)总是在内存中进行处理。

其次,在处理像您这样非常有效的LINQ查询时,有很多内部错误会导致异常。

第三,经过一些尝试和错误,以下等效结构适用于您的情况(至少不会产生异常):

.GroupBy(p => p.Member.MemberToSection.Select(m => m.Section.Name).FirstOrDefault())

(顺便说一句,与问题无关,p.Member.MemberToSection.Any调用中的s => s.MemberId == p.MemberId条件是多余的,因为它是由关系强制执行的,所以简单的Any()也会这样做。)

但现在不仅GroupBy是在内存中执行的,而且该查询在N+1 SQL查询中也引起了类似于EF Core嵌套的Linq select结果的N+1 SQL询问。祝贺:(

最新更新