GroupBy Entity Framework Core中查找表的第一個結果

asp.net-core c# entity-framework entity-framework-core

我試圖讓每個部分的志願者在日期範圍之間完成人工日。有一個出勤表,其中包括要映射到成員表的日期和成員ID。還有一個用於列出所有部分的部分錶和一個成員可以在多個部分中的成員表。

我想在成員所在的第一部分進行分組,然後計算該部分的所有出勤日數。

以下工作非常適合我在成員表上按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'

根據要求,這裡是相關的課程

Attendance.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; }
}

Member.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; }
}

Section.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不適合你(還)。以下適用於此時EF Core v1.1.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選擇N + 1 SQL查詢中的結果 。恭喜:(



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow