如何在 Linq 中按具有复杂类型的多列进行分组

How to group by multiple columns with complex types in Linq

我正在尝试按大学、状态对所有学生进行分组。问题是我正在使用的数据库在 StudentInfo table 中有数百个字段,这就是我认为这是失败的原因。

我基本上是想根据学生的状态来计算学生的数量,并根据他们来自的大学进行分组。

当我执行此查询时,出现以下异常。

调用 'GroupBy' 方法的键选择器类型在底层存储提供程序中不可比较。

现在我认为这是因为 StudentInfo table 上的字段太多了,但在这种情况下我对此无能为力。必须有办法做我想做的事。

我需要返回以下字段,所有字段都是计数,除了 College。

大专 |接受 |网络应用 |哎呀|总计

有人能给我指出正确的方向吗?

这是我的模型

public class EnrollmentCountsBySchool
{
    // selected terms
    public int[] SelectedTerms { get; set; }
    // list of terms
    public IEnumerable<SelectListItem> Terms { get; set; }

    // selected programs
    public int[] SelectedPrograms { get; set; }
    // list of programs
    public IEnumerable<SelectListItem> Programs { get; set; }

    // selected statuses
    public string[] SelectedStatuses { get; set; }
    // list of statuses
    public IEnumerable<SelectListItem> Statuses { get; set; }

    // list of results
    public List<EnrollmentCountsBySchoolResult> Results { get; set; }

我的查询(很长,我知道。)

 var results =
            (from student in db.StudentInfo
             join college in db.Colleges on student.College.Id equals college.Id
             where model.SelectedTerms.Contains(student.TermOfInterestId.Value) &&
                   model.SelectedPrograms.Contains(student.ProgramId.Value) &&
                   model.SelectedStatuses.Contains(student.Status)

             group student by new
             {
                 College = college.Name,
                 Accepts = (
                         from s in db.StudentInfo
                         join c in db.Colleges on student.College.Id equals college.Id
                         where model.SelectedTerms.Contains(student.TermOfInterestId.Value) &&
                               model.SelectedPrograms.Contains(student.ProgramId.Value) &&
                               model.SelectedStatuses.Contains(student.Status) &&
                               student.Status.ToLower().Contains("accepted") ||
                               student.Status.ToLower().Contains("applicant")
                         group s by new
                         {
                             College = c.Name,
                         } into accepts
                         select new
                         {
                             accepts.Key.College,
                             Count = accepts.Count()
                         }
                 ),
                 Webapps =
                 (
                         from s in db.StudentInfo
                         join c in db.Colleges on student.College.Id equals college.Id
                         where model.SelectedTerms.Contains(student.TermOfInterestId.Value) &&
                               model.SelectedPrograms.Contains(student.ProgramId.Value) &&
                               model.SelectedStatuses.Contains(student.Status) &&
                               student.Status.ToLower().Contains("webapp")
                         group s by new
                         {
                             College = c.Name,
                         } into webapps
                         select new
                         {
                             webapps.Key.College,
                             Count = webapps.Count()
                         }
                 ),
                 Ays = (
                         from s in db.StudentInfo
                         join c in db.Colleges on student.College.Id equals college.Id
                         where model.SelectedTerms.Contains(student.TermOfInterestId.Value) &&
                               model.SelectedPrograms.Contains(student.ProgramId.Value) &&
                               model.SelectedStatuses.Contains(student.Status) &&
                               !student.Status.ToLower().Contains("accepted") &&
                               !student.Status.ToLower().Contains("applicant") &&
                               !student.Status.ToLower().Contains("webapp")
                         group s by new
                         {
                             College = c.Name,
                         } into ays
                         select new
                         {
                             ays.Key.College,
                             Count = ays.Count()
                         }
                 ),
                 Total = (
                         from s in db.StudentInfo
                         join c in db.Colleges on student.College.Id equals college.Id
                         where model.SelectedTerms.Contains(student.TermOfInterestId.Value) &&
                               model.SelectedPrograms.Contains(student.ProgramId.Value) &&
                               model.SelectedStatuses.Contains(student.Status)
                         group s by new
                         {
                             College = c.Name,
                         } into totals
                         select new
                         {
                             totals.Key.College,
                             Count = totals.Count()
                         }
                 )

             }
                 into grouping
                 select new EnrollmentCountsBySchoolResult
                 {
                     College = grouping.Key.College,
                     Accepts = grouping.Key.Accepts.Count(),
                     Webapps = grouping.Key.Webapps.Count(),
                     Ays = grouping.Key.Ays.Count(),
                     Total = grouping.Key.Total.Count()
                 }).ToList();

我最终重写了按大学搜索并加入学生的查询,然后进行分组,我得到了我想要的结果。

       var results =
            from college in db.Colleges
            join student in db.StudentInfo on college.Id equals student.UniversityId
            where model.SelectedTerms.Contains(student.TermOfInterestId.Value) &&
                  model.SelectedPrograms.Contains(student.ProgramId.Value) &&
                  model.SelectedStatuses.Contains(student.Status)
            group college by new
            {
                College = college.Name,
                Accepts = (
                 from c1 in db.Colleges
                 join s1 in db.StudentInfo on c1.Id equals s1.UniversityId
                 where model.SelectedTerms.Contains(s1.TermOfInterestId.Value) &&
                       model.SelectedPrograms.Contains(s1.ProgramId.Value) &&
                       model.SelectedStatuses.Contains(s1.Status) &&
                       s1.UniversityId == college.Id &&
                       s1.Status.ToLower().Contains("accepted") || s1.Status.ToLower().Contains("applicant")
                 select c1
                ).Count(),
                Webapps = (
                    from c2 in db.Colleges
                    join s2 in db.StudentInfo on c2.Id equals s2.UniversityId
                    where model.SelectedTerms.Contains(s2.TermOfInterestId.Value) &&
                          model.SelectedPrograms.Contains(s2.ProgramId.Value) &&
                          model.SelectedStatuses.Contains(s2.Status) &&
                          s2.UniversityId == college.Id &&
                          s2.Status.ToLower().Contains("webapp")
                    select c2
                ).Count(),
                Ays = (
                    from c3 in db.Colleges
                    join s3 in db.StudentInfo on c3.Id equals s3.UniversityId
                    where model.SelectedTerms.Contains(s3.TermOfInterestId.Value) &&
                          model.SelectedPrograms.Contains(s3.ProgramId.Value) &&
                          model.SelectedStatuses.Contains(s3.Status) &&
                          s3.UniversityId == college.Id &&
                          !s3.Status.ToLower().Contains("accepted") && !s3.Status.ToLower().Contains("applicant") &&
                          !s3.Status.ToLower().Contains("webapp")
                    select c3
                ).Count()
            }
                into grouping
                select new EnrollmentCountsBySchoolResult
                {
                    College = grouping.Key.College,
                    Accepts = grouping.Key.Accepts,
                    Webapps = grouping.Key.Webapps,
                    Ays = grouping.Key.Ays,
                    Total = grouping.Count()
                };

        model.Results = results.OrderByDescending(o => o.Total).ToList();