C# 实体框架 OrderBy Children's Children's with a where 子句
Posted
技术标签:
【中文标题】C# 实体框架 OrderBy Children\'s Children\'s with a where 子句【英文标题】:C# Entity Framework OrderBy Children's Children's with a where clauseC# 实体框架 OrderBy Children's Children's with a where 子句 【发布时间】: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)
现在我担心性能,哈哈……但这将是另一个 *** 搜索 :)
【问题讨论】:
【参考方案1】:据我所知,你想使用 orderBy 然后简单地获取第一个元素,而你可以简单地获取具有相同谓词的第一个元素,降低 O(nlogn) 复杂度
var result = 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)))))
.FirstOrDefault(e => e.servicedt ?? e.planneddt) // you have 1 Encounters item
.EncounterItems.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)))))))));
【讨论】:
太棒了!看到)))))))));
关巢会吓到我?
你肯定不会是认真的...就这么简单吗??我明天在工作中试试,让你知道它是怎么回事。感谢您的快速回复。
HHmmm... 我收到此错误: System.ArgumentException: 'DbSortClause 表达式必须具有可与顺序比较的类型。参数名称:key'有什么想法吗?
感谢 Margus 的帮助...我已使用最终更新的 OrderBy 编辑了我的问题以上是关于C# 实体框架 OrderBy Children's Children's with a where 子句的主要内容,如果未能解决你的问题,请参考以下文章
具有实体框架并使用 orderby 和 skip/take 的规范模式