【问题标题】:How can you reuse a class in Entity Framework without using inheritance?如何在不使用继承的情况下重用实体框架中的类?
【发布时间】:2015-12-18 13:20:12
【问题描述】:

我有一堆从其他各种类引用的简单类。例如,

class Version {
    // PK is Major, Minor, Build, Revision
    int Major { get; set; }
    int Minor { get; set; }
    int Build { get; set; }
    int Revision { get; set; }
}

class DraftArticle {
    int Id { get; set; }
    string Title { get; set; }
    string Description { get; set; }
    ICollection<Version> AffectedVersions { get; set; }
}

class Article {
    int Id { get; set; }
    string Title { get; set; }
    string Description { get; set; }
    ICollection<Version> AffectedVersions { get; set; }
}

class DbContext : System.Data.Entity.DbContext {
    System.Data.Entity.DbSet<DraftArticle> DraftArticles { get; set; }
    System.Data.Entity.DbSet<Article> Articles { get; set; }
}

当按照上面发布的方式使用时,Entity Framework 将创建三个表——[DraftArticles]、[Articles] 和 [Versions],其中 [Versions] 表将具有以下 extra 列—— [判别器]、[DraftArticle_Id] 和 [Article_Id]。

我的目标是将 DraftArticles 和 Articles 的版本记录分开到单独的表中。

我知道这可以使用inheritance 和/或ComplexType 完成,但我想避免使用这两种方法,因为它需要额外的类。

例如,以下添加和修改工作

// additions
class DraftArticleVersion : Version { }

class ArticleVersion : Version { }

// modifications
class DraftArticle {
    ...
    ICollection<DraftArticleVersion> AffectedVersions { get; set; }
}

class Article {
    ...
    ICollection<ArticleVersion> AffectedVersions { get; set; }
}

class DbContext : System.Data.Entity.DbContext {
    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Entity<DraftArticleVersion>().Map(m => {
            m.MapInheritedProperties();
            m.ToTable("DraftArticleAffectedVersions");
        });

        modelBuilder.Entity<DraftArticleVersion>().Map(m => {
            m.MapInheritedProperties();
            m.ToTable("ArticleAffectedVersions");
        });
    }

    ...
}

此外,当使用像AutoMapper 这样的框架时,它需要额外的(重复的)映射定义。

理想情况下,我希望看到类似于ToTable() 应用于属性 级别的内容而不是在 Class 级别。例如,

class Version {
    // PK is Major, Minor, Build, Revision
    ...
}

class DraftArticle {
    ...
    ICollection<Version> AffectedVersions { get; set; }
}

class Article {
    ...
    ICollection<Version> AffectedVersions { get; set; }
}

class DbContext : System.Data.Entity.DbContext {
    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        // somehow apply .ToTable("DraftArticleAffectedVersions") to DraftArticle.AffectedVersions

        // somehow apply .ToTable("ArticleAffectedVersions") to Article.AffectedVersions
    }

    ...
}

有人知道这是否可以做到吗?您是否知道有任何其他方法可以重用类而无需创建额外的类和/或映射?

【问题讨论】:

  • 您是说您想要一个版本表用于文章,另一个版本表用于 DraftArticles?
  • 我想部分问题是我不知道你为什么要将版本分成两个表。如果版本确实不相关,那么它们应该是恰好具有相同字段的单独实体。
  • 你会遇到维护的噩梦,文章、草稿等都非常相似,正确的设计是只有一个表并设置一个状态字段,上面写着“草稿”、“已发布”,这就是每个博客的做法。如果你想实现文章和草稿之间的一对多关系,那么你可以创建一个自父子关系。
  • @Fabio -- 正确。不同文章类型的单独表格。他们只是碰巧都有版本属性。那么为什么要创建重复的类。维护头痛。
  • @Vlad274 / @Akash -- 请解释为什么“正确”的设计是将它们放在同一张表中?它们服务于不同的目的。也许我有一个用于知识库文章的“文章”表和另一个用于技术说明文章的“文章”表。并且这两种类型的文章除了具有相同的类属性之外是无关的。问题是关于避免创建不必要的(重复的)类。实际上,我认为维护具有相同确切属性的不同类更像是维护噩梦。需要多次更改。

标签: entity-framework inheritance mapping entity-framework-6


【解决方案1】:

正如 cmets 所暗示的 - 你不会喜欢答案,即你正在尝试做一些没有多大意义的事情,因此 EntityFramework 不支持它。

通过说 Article 和 Draft 都有一个“版本”列表,您已经告诉 EF 两者指的是同一个东西 - 因此是一个表。但是您说您希望它们指代不同的事物。为什么?

正如 Akash 所说,更好(更规范化)的设计将避免需要这种奇怪的结果。

【讨论】:

  • 因为本质上它们是不同的——从实体的角度来看。问题是关于重用类定义和减少维护。我试图让我的示例保持简单,但我认为每个人都过于关注草稿与已发表的文章。也许一个更好的例子是文章和支持票。两个 完全 不同的实体,但它们都可能具有完全不同的版本对象集合,这些对象恰好具有相同的属性。想看看我是否可以重用我的 Version 类。显然不是……
  • 是的,我可以看到您想要实现的目标,显然 EF 不支持。但是,它们如何“完全不同”?它们实际上似乎是完全相同的东西,一个通用的“版本”,遵循通常的规范化,应该放在一个表中。
  • 很抱歉在这么长时间的休息后回到这里。最终,虽然我不同意将它们放在同一张表中是正确的方法,但这个答案确实解决了我的问题,即“EF 不支持它”,所以我将其标记为这样。
猜你喜欢
  • 2016-01-03
  • 1970-01-01
  • 2011-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-15
  • 2011-09-14
  • 1970-01-01
相关资源
最近更新 更多