实体框架6代码优先:具体的模型设计实现

时间:2014-11-12 11:59:13

标签: entity-framework ef-code-first

我有一个小模特,但我对如何设计有疑问。

我的想法是有三个类:JobReport / Customer / Project。 范围是填充选择Customer的报告,然后填充绑定到其客户的Project(以及其他有效负载)。

我的设计是:

Design 1

MODEL:

public class EFDBContext : DbContext
{
    public DbSet<JobReport> JobReport { get; set; }
}

当我脚手架JobReport View并使用它的模型时,我发现difficoult绑定Customer实体,因为它直接绑定到Project而不是JobReport。 另一个解决方案是将CustomerID和ProjectID都放入JobReport,但在我看来它是多余的。

Design 2

我有两种可能性: 1-保留第一个模型并分别使用JobReport和Customer创建ViewModel 2-使用第二个模型,以便我拥有所有ID。

你怎么看? 你会如何实施这个案子?

非常感谢!!

最高

1 个答案:

答案 0 :(得分:0)

有几点意见:

  • 设计1似乎合适,除非一个JobReport应该能够引用属于不同客户的多个项目。
  • ProjectID属性不属于Customer类型,对吧?不过,Projects系列是理所当然的。
  • 项目类型应具有JobReports集合,该集合列出属于特定对象的所有报告。

这是一个与在域驱动设计中识别聚合的讨论密切相关的问题。您的Customer实体似乎是一个自然聚合根,这意味着与聚合内对象的所有交互都必须通过客户。

这意味着DbContext应该是这样的:

public class EFDBContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }
}

要获得属于客户的子项,可以使用LINQ遍历关系:

public IEnumerable<JobReport> GetReportsByCustomer(int customerId)
{
    using (var context = new EFDBContext())
    {
        return context.Customers.Where(x => x.CustomerID.Equals(customerId))
            .SelectMany(x => x.Projects)
            .SelectMany(x => x.JobReports)
            .OrderBy(x => x.Timestamp);
    }
}

您还可以选择始终使用客户作为编辑操作的基础,因为它是聚合根。这将涉及将客户拉出数据库并确保包含所有详细数据:

public IEnumerable<Customer> GetCustomer(int customerId)
{
    using (var context = new EFDBContext())
    {
        return context.Customers
            .Include(x => x.Projects.Select(y => y.JobReports))
            .FirstOrDefault(x => x.CustomerID.Equals(customerId));
    }
}

您需要在类文件的顶部手动添加using System.Data.Entity;才能使上述代码生效。