【发布时间】:2022-01-16 02:30:02
【问题描述】:
我有一个非常复杂的 linq 语句,它获取人员列表(使用实体框架),我想在末尾添加一个 OrderBy 子句,具体取决于用户单击哪个列进行排序。我不想让所有人都进行排序,因为可能有很多人,而且我们也进行分页,所以获取数据然后排序/分页不是一种选择。因此必须使用 LINQ to EF 来完成。
我已设法获得根据用户当前疫苗接种状态进行过滤的搜索条件,但我无法将其“转换”为 OrderBy 声明
我获得的数据与 COVID 疫苗接种有关,以及此人的疫苗接种状态是完全、部分、未披露还是无。
带有Where 子句的实体框架LINQ 语句如下所示,它是IQueryable<Person>,而不是List<Person>:
people.Where(p => p.Encounters.Where(e =>
e.EncounterItems.Any(ei => ei.PersonAssessments.Any(pa =>
pa.Assessment.Questions.Any(q => q.questioncode.Equals("qIDateF", StringComparison.InvariantCultureIgnoreCase) || q.questioncode.Equals("qIDateP", StringComparison.InvariantCultureIgnoreCase)))))
.OrderByDescending(e => e.servicedt ?? e.planneddt).FirstOrDefault()
.EncounterItems.Where(ei =>
ei.PersonAssessments.Any(pa => pa.Answers.Any(a => a.adate.HasValue && DbFunctions.AddMonths(a.adate, procedureCycleDays) < DateTime.Today &&
(a.Question.questioncode.Equals("qIDateF", StringComparison.InvariantCultureIgnoreCase) || (a.Question.questioncode.Equals("qIDateP", StringComparison.InvariantCultureIgnoreCase)
&& (!pa.Answers.Any(aa => aa.adate.HasValue && aa.Question.questioncode.Equals("qIDateF", StringComparison.InvariantCultureIgnoreCase)))
))))).FirstOrDefault()
!= null)
它会从上面筛选出疫苗接种状态为“过期”的人。即他们已经进行了部分或全部疫苗接种,但已超过该疫苗接种的周期。问题代码的“qIDateP”(部分)和“qIDateF”(完整)有 2 个问题。
我知道下面的OrderBy 是完全错误的,但我想做这样的事情,以便所有疫苗接种状态过期的人都在顶部。然后,我将使用相同的子句添加其他几个OrderBy 子句,例如“Current”,只是链接日期表达式,例如DbFunctions.AddMonths(a.adate, procedureCycleDays) >= DateTime.Today
people.OrderBy(p => p.Encounters.Where(e =>
e.EncounterItems.Any(ei => ei.PersonAssessments.Any(pa =>
pa.Assessment.Questions.Any(q => q.questioncode.Equals("qIDateF", StringComparison.InvariantCultureIgnoreCase) || q.questioncode.Equals("qIDateP", StringComparison.InvariantCultureIgnoreCase)))))
.OrderByDescending(e => e.servicedt ?? e.planneddt).FirstOrDefault()
.EncounterItems.Where(ei =>
ei.PersonAssessments.Any(pa => pa.Answers.Any(a => a.adate.HasValue && DbFunctions.AddMonths(a.adate, procedureCycleDays) < DateTime.Today &&
(a.Question.questioncode.Equals("qIDateF", StringComparison.InvariantCultureIgnoreCase) || (a.Question.questioncode.Equals("qIDateP", StringComparison.InvariantCultureIgnoreCase)
&& (!pa.Answers.Any(aa => aa.adate.HasValue && aa.Question.questioncode.Equals("qIDateF", StringComparison.InvariantCultureIgnoreCase)))
))))).FirstOrDefault()
!= null)
EF 模型的关系如下:
Person => Encounter => EncounterItem => PersonAssessment => Answer
一个人可以在一生中回答多项评估,并且可以改变他们是否要披露其疫苗接种状态的想法。
注意:我们使用的是最新的 Entity Framework 6.4.4
我希望有人可以帮助我处理 OrderBy 子句,因为我完全不知道如何实现这一点。
-----更新 1-------
到目前为止,我一直在使用它。
people.OrderBy(p => p.Encounters.Where(
e => e.EncounterItems.Any(
ei => ei.PersonAssessments.Any(
pa => pa.Assessment.Questions.Any(
q => q.questioncode.Equals("qIDateF", StringComparison.InvariantCultureIgnoreCase)
|| q.questioncode.Equals("qIDateP", StringComparison.InvariantCultureIgnoreCase))))).OrderByDescending(e => e.servicedt ?? e.planneddt).FirstOrDefault() // you have 1 Encounters item
.EncounterItems.DefaultIfEmpty().FirstOrDefault(
ei => ei.PersonAssessments.Any(
pa => pa.Answers.Any(
a => a.adate.HasValue
&& DbFunctions.AddMonths(a.adate, procedureCycleDays) < DateTime.Today
&& (a.Question.questioncode.Equals("qIDateF", StringComparison.InvariantCultureIgnoreCase)
|| (a.Question.questioncode.Equals("qIDateP", StringComparison.InvariantCultureIgnoreCase)
&& (!pa.Answers.Any(aa => aa.adate.HasValue && aa.Question.questioncode.Equals("qIDateF", StringComparison.InvariantCultureIgnoreCase)))))))).Encounter.planneddt)
问题是所有“过期”记录都在底部,而不是顶部。如果我使用OrderByDescending,它似乎是正确的。我现在如何使用OrderBy 而不是OrderByDescending 将所有这些记录放在顶部。
------ UPDATE 2 最终解决方案 ------
根据下面的Margus 答案进行了几次更改后,我得到了最终更新的OrderBy。出于某种原因,我不得不OrderBydescending 才能获得我想要的记录。
people.OrderByDescending(p => p.Encounters.Where(
e => e.EncounterItems.Any(
ei => ei.PersonAssessments.Any(
pa => pa.Assessment.Questions.Any(
q => q.questioncode.Equals("qIDateF", StringComparison.InvariantCultureIgnoreCase)
|| q.questioncode.Equals("qIDateP", StringComparison.InvariantCultureIgnoreCase))))).OrderByDescending(e => e.servicedt ?? e.planneddt).FirstOrDefault() // you have 1 Encounters item.EncounterItems.DefaultIfEmpty().FirstOrDefault(
ei => ei.PersonAssessments.Any(
pa => pa.Answers.Any(
a => a.adate.HasValue
&& DbFunctions.AddMonths(a.adate, procedureCycleDays) < DateTime.Today
&& (a.Question.questioncode.Equals("qIDateF", StringComparison.InvariantCultureIgnoreCase)
|| (a.Question.questioncode.Equals("qIDateP", StringComparison.InvariantCultureIgnoreCase)
&& (!pa.Answers.Any(aa => aa.adate.HasValue && aa.Question.questioncode.Equals("qIDateF", StringComparison.InvariantCultureIgnoreCase)))))))).Encounter.planneddt)
现在我担心性能,哈哈……但这将是另一个 stackoverflow 搜索 :)
【问题讨论】:
标签: c# entity-framework linq sql-order-by