简体   繁体   中英

Linq query with Include to count joined records

I"m using Linqpad connection to Entity Framework to form my Linq query, it's great for seeing your results without having to run your app.. Anyway, I have an Events table, that is joined to an EventStudent table. The EventStudent table will have 0 to many records for each Event. I want to return an event date and title along with the number of students who attended. The EventStudent table has the student as well as a boolean 'attended' field.

With this query, I get all the event data and all the student data for each event - this is good!

from ev in Events.Include("EventStudents")
where (ev.StartDate >= new DateTime(2012, 7, 1) && ev.StartDate <= new DateTime(2013, 6, 30))
orderby ev.StartDate descending
select ev

What I want is the Event information and the COUNT of students who attended, so I can bind this to a grid. This is what I have tried:

from ev in Events.Include("EventStudents")
where (ev.StartDate >= new DateTime(2012, 7, 1) && ev.StartDate <= new DateTime(2013, 6, 30))
orderby ev.StartDate descending
select new { ev.EventID, ev.StartDate, ev.Title, ev.EventStudents.Count() }

But I get an error "anonymous type member declarator must be simple name... ". Ok, but, how can I get my event data and the count of students all in one type to bind to my grid? If it matters - the grid has a 'select' column, this is why the event ID is included - it will be hidden in the grid. Plus, the grid will have sorting and filtering abilities. And... how can I return the date from the Linq query with date only (no time?).

Thank you!

Try this. This gets the date from StartDate by using the .Date property. And it names the result of the Count() call as "StudentCount".

select new { ev.EventID, ev.StartDate.Date, ev.Title, StudentCount = ev.EventStudents.Count() }

You're query is fine. The only problem is that you need to provide a name for the Count member. Like this:

from ev in Events.Include("EventStudents")
where (ev.StartDate >= new DateTime(2012, 7, 1) && ev.StartDate <= new DateTime(2013, 6, 30))
orderby ev.StartDate descending
select new 
{ 
    ev.EventID, 
    ev.StartDate, 
    ev.Title, 
    Count = ev.EventStudents.Count() 
}

From MSDN :

If you do not specify member names in the anonymous type, the compiler gives the anonymous type members the same name as the property being used to initialize them. You must provide a name for a property that is being initialized with an expression…

You also mentioned you wanted to get the date part only. You can use the TruncateTime function, like this:

from ev in Events.Include("EventStudents")
where (ev.StartDate >= new DateTime(2012, 7, 1) && ev.StartDate <= new DateTime(2013, 6, 30))
orderby ev.StartDate descending
select new 
{ 
    ev.EventID, 
    StartDate = EntityFunctions.TruncateTime(ev.StartDate.Date), 
    ev.Title, 
    Count = ev.EventStudents.Count() 
}

Note you may have to cast the input of this function to a Nullable<DateTime> first, like this:

    StartDate = EntityFunctions.TruncateTime((DateTime?)ev.StartDate.Date), 

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM