如何在 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();
我正在尝试按大学、状态对所有学生进行分组。问题是我正在使用的数据库在 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();