I have a pretty complicated linq statement that gets a list of people (using Entity Framework) and I want to add an OrderBy
clause to the end, depending on which column the user has clicked on for sorting. I DON'T want to get all the people and then sort as there are potentially alot of people and we also do paging, so getting the data and then sorting/paging is not an option. It must therefore be done using LINQ to EF.
I have managed to get the search criteria that filters based on the status of the user's current vaccination status, but I am unable to "convert" that to an OrderBy
statement
The data I am getting relates to COVID vaccinations and whether the person's vaccination status is Full, Partial, Not Disclosed or None.
The Entity Framework LINQ statement with the Where
clause looks like this and It is an IQueryable<Person>
, not a 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)
From the above it will filter the people where their vaccination status is "Overdue". ie they have done either Partial or Full Vaccination but the cycle for this vaccination has been exceeded. There are 2 questions with questioncode's "qIDateP" (partial) and "qIDateF" (full).
I know the below OrderBy
is completly wrong, but I want to do something like this so that all the people with overdue vaccination status's are at the top. I will then add several other OrderBy
clauses such as "Current" using the same clause, just chainging the date expression eg 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)
The Relationships for the EF Models is as follows:
Person => Encounter => EncounterItem => PersonAssessment => Answer
A person can answer multiple Assessments over their life and can change their mind as to whether they want to disclose their vaccination status or not.
NOTE: We are using the latest Entity Framework 6.4.4
I hope someone can help me with the OrderBy clause as Im at a complete loss as to how to achieve this.
Well as far as I can tell you want to use orderBy and then simply fetch the first element, while you could simply fetch the first element with the same predicate dropping O(nlogn) complexity
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)))))))));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.