所以你有项目和时间条目。 Project 和 TimeEntry 之间存在一对多的关系:每个 Project 都有零个或多个 TimeEntry,每个 TimeEntry 恰好属于一个 Project。
如果您关注the entity framework code first conventions,,您将创建如下类:
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;}
}
因为您遵循约定,这足以告知实体框架您计划了一对多。 Entity Framework 将能够检测主键和外键以及 Projects 和 TimeEntries 之间的关系(可能的问题:时间条目的复数化)。
如果您想要不同的表名或列名,则需要属性或流畅的 API。但结构仍然相似。
所以现在你有了你的项目和时间条目。对于每个项目,您都希望 TimeWorked 在给定时间间隔内的 TimeEntries 数量(您确定吗?您想要计数,而不是工作时间的总和?)
我愿意这样做:
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(),
});
因为我使用了 ICollections,实体框架会在内部进行适当的连接来计算结果。
如果您想自己指定连接,我会这样做:
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(),
如果您不熟悉实体框架代码的基础知识。 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