Reputation: 245
I am trying to perform an aggregate count() just like a SQL query would against my database, but instead of SQL I want to use LINQ.
I am trying to use LINQ to query my Entity Framework Data Model and perform an aggregate sum(). Specifically I want to do a count of the column(TimeWorked) in the TimeEntry table grouping by Project Name and Phase between 2 specific dates and then do a natural join on the Project table. I am then going to take that query result and load it into an observable collection and display it in a ListView.
My desired result is [ProjectName],[Phase],[Count(TimeWorked)],[Date] I want to filter the counting to only Projects with a TimeEntry that is between two dates that for the sake of this example will just be called Date1 and Date2.
I am not familiar with LINQ 100% yet, I am still learning so please excuse my lack of LINQ terminology.
Here is a picture of my Relationship and tables. DB Schema
Here are the data types Project Table data types, TimeEntry table
I have been looking everywhere and can't seem to find any good resources or examples. Could someone please point me in the right direction.
Upvotes: 0
Views: 218
Reputation: 30464
So you have projects and timeentries. There is a one-to-many relation between a Project and a TimeEntry: every Project has zero or more TimeEntries, every TimeEntry belongs to exactly one Project.
If you'd followed the entity framework code first conventions, you would have created classes like this:
class Project
{
public int Id {get; set;}
// every Project has zero or more TimeEntries:
public virtual ICollection<TimeEntry> TimeEntries {get; set;}
... // other properties
}
class TimeEntry
{
public int Id {get; set;}
// every TimeEntry belongs to exactly one Project using foreign key:
public int ProjectId {get; set;}
public virtual Project Project {get; set;}
... // other properties
}
class MyDbContext : DbContext
{
public DbSet<Project> Projects {get; set;}
public DbSet<TimeEntry> TimeEntries {get; set;}
}
Because you followed the conventions, this would be enough to inform entity framework that you planned a one-to-many. Entity Framework would be able to detect the primary and foreign keys and the relation between Projects and TimeEntries (possible problem: pluralization of time entry).
If you want different table names or column names, you'll need attributes or fluent API. But the structure remains similar.
So now you have your Project and TimeEntries. You want for every Project the Number of TimeEntries where TimeWorked is in a given time interval (are you sure? you want the Count, not the sum of time worked?)
I'd go for this:
var projectWithCountTimeWorked = dbContext.Projects
.Select(project => new
{
ProjectName = project.ProjectName,
...
// the Count of TimeEntries of this project in this period:
CountTimeWorked = project.TimeEntries
.Where(timeEntry => minDate <= timeEntry.TimeWorked
&& timeEntry.TimeWorked <= maxDate)
.Count(),
});
Because I used the ICollections, entity framework will internally do the proper joins to calculate the result.
If you want to specify the joins yourself I'd go for this:
var result = dbContext.Project // GroupJoin Projects
.GroupJoin(dbContext.TimeEntries // and TimeEntries
project => project.Id, // from every Project take the Id
timeEntry => timeEntry.ProjectId, // from every timeEntry take the ProjectId
(project, timeEntries) => new // for every Project and his matching
{ // timeEntries make a new object
Name = project.Name,
...
CountTimeWorked = timeEntries // count all timeEntries during the period
.Where(timeEntry => minDate <= timeEntry.TimeWorked
&& timeEntry.TimeWorked <= maxDate)
.Count(),
If you are unfamiliar with entity-framework code first basics. This web site helped me a lot to get me on track
This article was a good summary for me to have a look at most used linq methods
Upvotes: 1