【问题标题】:Perform aggregate count() on ADO.net Entity data model在 ADO.net 实体数据模型上执行聚合 count()
【发布时间】:2018-02-20 13:43:51
【问题描述】:

我正在尝试执行聚合计数(),就像对我的数据库的 SQL 查询一样,但我想使用 LINQ 而不是 SQL。

我正在尝试使用 LINQ 来查询我的 Entity Framework 数据模型 并执行 聚合 sum()。具体来说,我想对 TimeEntry 表中的列(TimeWorked)进行计数,按项目名称和阶段在 2 个特定日期之间进行分组,然后在项目表上进行自然连接。然后,我将获取该查询结果并将其加载到可观察的集合中,并将其显示在 ListView 中。

我想要的结果是 [ProjectName],[Phase],[Count(TimeWorked)],[Date] 我想将计数过滤到只有两个日期之间的 TimeEntry 的项目,为了这个示例,它们将被称为 Date1 和 Date2。

我还不熟悉 LINQ 100%,我还在学习,所以请原谅我缺乏 LINQ 术语。

这是我的关系和表格的图片。 DB Schema

这里是数据类型 Project Table data types, TimeEntry table

我到处寻找,似乎找不到任何好的资源或示例。有人能指出我正确的方向吗?

【问题讨论】:

  • 该图仅显示名称。在 EF 中,最重要的是类及其属性和类型。你也可以用 LINQ/EF 术语说话。什么是列数自然连接等。发布您的实体类和所需的结果(类)类型。

标签: sql entity-framework linq listview aggregate-functions


【解决方案1】:

所以你有项目和时间条目。 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

【讨论】:

  • 不,我打错字了,我在项目中输入了 sum()
  • 这对我来说看起来不错,我对所有这些语法都不熟悉,你知道我可以阅读的任何好的参考资料可以帮助我理解你到底在做什么吗?它可以理解正在发生的事情,它正是我正在寻找的,只是以前从未使用过这样的 LINQ 语句。
  • 我想你会明白要点的,你会知道我的回答要改变什么
  • 所以我认为查询工作正常,现在我只需要找到一种方法将其填充到我的列表视图中。我正在尝试维护 MVVM,您知道将此查询绑定到 ListView 的方法吗?
  • 我对 ListView 不是很熟悉。我想这与将数据绑定到 DataGridView 的方式类似:使用 BindingSource。 BindingSource 的类型取决于你想要的功能,比如排序
猜你喜欢
  • 2013-01-04
  • 1970-01-01
  • 2014-05-27
  • 1970-01-01
  • 2018-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多