LINQ Order by question - linq

I have a linq query that returns a list of employees and a job title.
I need to sort it by job title but have the ones that do not have any employees in the output list first.
Example sorted:
- Driver List{0}
- Attendant List{71}
- Pilot List{19}
The driver is first because it has nothing in the list and then it is sorted by title.
I am just curious what do you think would be my best option to accomplish that?
Thanks

Something like:
var query = employees.OrderBy(x => x.Subordinates.Any() ? 1 : 0)
.ThenBy(x => x.JobTitle);
You could also use the fact that false sorts earlier than true:
var query = employees.OrderBy(x => !x.Subordinates.Any())
.ThenBy(x => x.JobTitle);
... but that's a little bit less obvious, IMO.

Something like:
Jobs.OrderBy(j => j.Eployees.Count()).ThenBy(j => j.Name);

Related

filtering a collection by its children in linq to entities?

I have the following query which filters the batches according to whether the items in the batches have a certain issue no. I would like to know if there is more concise way doing this which would look cleaner.
neptuneBatches =
neptuneBatches.Where(
b => b.Items.Any(
i => i.ItemOrganisations.Any(
s => s.Issues.Any(
x => x.Code == filter.IssueNo))));

linq filtering child collection

I have read over a bunch of different topics on this, but i havent found what I am looking for.
I have an EF query that is this:
var query = this.ObjectContext.Questions
.Include("AnswerKey").Include("QuestionTypes")
.Where(o => o.SurveyQuestions.Any(o2 => o2.SurveyID == id));
This was working fine until i realized that i was not taking into account my Active Flag for the AnswerKey child collection. In other words, this query should load all questions that have a parent surveyid of 3(which it does)but only load AnswerKeys that have an active flag of true.
I have tried this:
var query = this.ObjectContext.AnswerKey
.Include("Questions.QuestionTypes")
.Where(ak =>
ak.Active == true &&
ak.Questions.SurveyQuestions.Any(sq => sq.SurveyID == 3) &&
ak.Questions.Active == true)
.AsEnumerable()
.Select(ak => ak.Questions).AsQueryable();
But it returns 1 question for each answerkey. So if a question has 4 answer it shows up 4 times...
How can i do this?
You could just use Distinct() at the end to filter out the duplicates:
.AsEnumerable()
.Select(ak => ak.Questions)
.Distinct()
.AsQueryable();
Brokenglass I will try your suggestion. And give you the credit if it works..
I also found this here after following another link on SO... and this appears to work as well but i need to verify it in my app.

How do I merge two LINQ statements into one to perform a list2.Except(list1)?

Currently, I have the following LINQ queries. How can I merge the two queries into one. Basically, write a LINQ query to bring back the results I'd get from
IEnumerable<int> deltaList = people2010.Except(allPeople);
except in a single query.
var people2010 = Contacts.Where(x => x.Contractors
.Any(d => d.ContractorsStatusTrackings
.Any(date => date.StatusDate.Year >= 2010)))
.Select(x => x.ContactID);
var allPeople = Contacts.Where(x => x.Contractors
.Any(m => m.ContactID == x.ContactID))
.Select(x=> x.ContactID);
Thanks!
Why can you not just do Except as you are doing? Don't forget that your people2010 and allPeople variables are just queries - they're not the data. Why not just use them as they are?
If that's not acceptable for some reason, please give us more information - such as whether this is in LINQ to Object, LINQ to SQL etc, and what's wrong with just using Except.
It sounds like you're just looking for a more elegant way to write your query. I believe that this is a more elegant way to write your combined queries:
var deltaList =
from contact in Contacts
let contractors = contact.Contractors
where contractors.Any(ctor => ctor.ContractorStatusTrackings
.Any(date => date.StatusDate.Year >= 2010))
&& !contractors.Any(m => m.ContactID == contact.ContactID)
select contact.ContactID

Count in lambda expression

I am trying to run a query where I get the name of locations and the number of items in that location. So if i have a program that contains 3 locations I want to know how many programs are in that location..I need to use this with a lambda expression or linq to entities.
return Repository.Find(x => x.Location.Name.Count())...clearly missing something here.
we'll just assume I have a Program entity with ProgramID, ProgramName, LocationName...need to know how many programs are in at a location
You can do it like this:
return repository.Count(x => x.Location == "SomeLocation");
Do you want to know the counts for all locations at once?
var locCounts = Repository.GroupBy(prog => prog.Location.Name).ToLookup(g => g.key, g => g.Count());
if you will repositoryPattern, use this code
Clients.Where(p => p.DateOfArrival >= DateTime.Now.AddDays(-3) && p.DateOfArrival <= DateTime.Now.AddDays(3)).Select(p => p.ID).Count()
Repository Pattern

Optimising Lambda Linq to SQL query with OrderBy

I have the following lambda expression:
IEnumerable<Order> query
= _ordersRepository.GetAllByFilter(
o =>
o.OrderStatus.OrderByDescending(os => os.Status.Date).First()
.Status.StatusType.DisplayName != "Completed"
||
o.OrderStatus.OrderByDescending(os => os.Status.Date).First()
.Status.Date > sinceDate
).OrderBy(o => o.DueDate);
As you can see, I'm having to order the collection twice within the main query (so three times in total) in order to perform my OR query.
1) Is the query optimiser clever enough to deal with this in an efficient way?
2) If not, how can I rewrite this expression to only order by once, but keeping with lambda syntax?
This is linked to this previous question, which explains the query in a bit more detail if the above code isn't clear.
1) Is the query optimiser clever enough to deal with this in an efficient way?
You can get the SQL for this query (one way is to use the SQL profiler), and then ask SQL Studio for the execution plan. Unless you do this, there is no way to know what the optimizer thinks. My guess is the answer is "no".
2) If not, how can I rewrite this expression to only order by once, but keeping with lambda syntax?
Like this:
IEnumerable<Order> query = _ordersRepository.GetAllByFilter( o =>
o.OrderStatus
.OrderByDescending(os => os.Status.Date)
.Take(1)
.Any(os => os.Status.StatusType.DisplayName != "Completed"
|| os.Status.Date > sinceDate)
})
.OrderBy(o => o.DueDate);
Regarding your first point: You can see the SQL that is generated by subscribing to the output of the DatabaseContext object. This is usually in a property called Log.
As for optimising your query, try the following (I've not tested it so I don't know if it will work)
IEnumerable<Order> query
= _ordersRepository.GetAllByFilter(
o =>
o.OrderStatus.Max(os => os.Status.Date).Any(os =>
os.Status.StatusType.DisplayName != "Completed"
|| os.Status.Date > sinceDate)
).OrderBy(o => o.DueDate);
Hopefully that will only perform the subquery once, and also performs a max rather than an order by with top 1.

Resources