【问题标题】:Modelling polymorphic associations database-first vs code-first建模多态关联数据库优先与代码优先
【发布时间】:2012-12-06 21:09:10
【问题描述】:

我们有一个数据库,其中一个表包含可以是其他几个表的子记录的记录。它有一个由所有者 ID 和表名组成的“软”外键。这种(反)模式被称为“多态关联”。我们知道这不是最好的数据库设计,我们会在适当的时候改变它,但不会在不久的将来。让我展示一个简化的例子:

EventPersonProduct 在评论中都有记录。如您所见,没有硬性 FK 约束。

在实体框架中,可以通过将Comment 子类化为EventComment 等来支持此模型,并让Event 拥有一个EventComments 集合等:

从数据库生成基本模型后,手动添加子类和关联。 OwnerCode 是这个 TPH 模型中的判别器。请注意EventPersonProduct 是完全不同的实体。为它们创建一个通用的基类是没有意义的。

这是数据库优先的。我们的真实模型是这样工作的,没问题。

好的。现在我们要转向代码优先。所以我开始将数据库逆向工程为代码优先模型(EF Power Tools),然后继续创建子类并映射关联和继承。试图连接到 Linqpad 中的模型。这就是麻烦开始的时候。

当尝试使用此模型执行查询时,它会抛出 InvalidOperationExeception

外键组件“OwnerId”不是“EventComment”类型的声明属性。验证它没有被明确地从模型中排除,并且它是一个有效的原始属性。

当我有双向关联并且OwnerId 被映射为Comment 中的一个属性时,就会发生这种情况。我的EventMap 类 (EntityTypeConfiguration<Event>) 中的映射如下所示:

this.HasMany(x => x.Comments).WithRequired(c => c.Event)
    .HasForeignKey(c => c.OwnerId);

所以我尝试在模型中映射没有OwnerId 的关联:

this.HasMany(x => x.Comments).WithRequired().Map(m => m.MapKey("OwnerId"));

这会引发MetaDataException

指定的架构无效。错误: (10,6) : 错误 0019: 类型中的每个属性名称必须是唯一的。已定义属性名称“OwnerId”。 (11,6) : 错误 0019: 类型中的每个属性名称必须是唯一的。已定义属性名称“OwnerId”。

如果我删除三个实体评论关联中的两个,那没关系,但这当然不是治愈方法。

更多细节:

  • 可以通过添加一个 DbContext 生成器项从 edmx 创建一个有效的 DbContext 模型(“第二个代码”)。 (这暂时是一种解决方法)。
  • 当我将工作代码优先模型(具有一个关联)导出到 edmx (EdmxWriter) 时,关联似乎在存储模型中,而在原始 edmx 中它们是概念模型的一部分。

那么,我怎样才能先代码创建这个模型呢?我认为关键是如何指示代码优先映射概念模型中的关联,而不是存储模型。

【问题讨论】:

  • 你有没有让模型与 Code-First 一起工作?有趣的是它适用于 Db-First/EDMX。我有一个关于类似模型的问题,CodePlex 的最后一句话基本上是“不支持”和“基本的 EF 限制”(stackoverflow.com/a/14880084/270591)。但是,如果您的模型与 EDMX 一起使用,它实际上似乎是 Code-First 限制,而不是一般的 EF 限制。
  • 是的,数据库优先模型有效(感谢上帝)。真实模型甚至更复杂,因为它具有复合继承鉴别器。没问题。代码优先是问题所在。你试过你的模型 db-first 吗?
  • 不,从未尝试过。我们知道 Code-First 不支持所有 edmx 功能,但我真的没想到这种情况会有所不同。顺便说一句,我刚刚要求确认 CodePlex 上的那个旧问题(entityframework.codeplex.com/workitem/865,页面上的最后评论)。不确定我是否可以在已关闭的项目中得到答案。
  • 也许他们会,会很有趣。我认为关键在于存储模型和概念模型之间的区别,但我无法理解为什么这会如此重要。无论如何,这一切都促使我在清理我们的模型(将其转变为更体面的 3NF 模型)方面付出更多的努力,因为这显然是一个非常基本的限制,可能会导致我们的 db-first 模型在未来的 EF 版本中也崩溃。
  • 我认为问题在于 OwnerType 应该只在子类中定义(应该从 Comment 类中删除)。我可以在这里工作stackoverflow.com/questions/38275335/…

标签: c# ef-code-first foreign-keys entity-framework-5 ef-database-first


【解决方案1】:

在这种复杂程度的任何架构上使用 EF 时,我个人首先坚持使用数据库。关于代码,我遇到了复杂模式的问题。也许较新的版本更好一些,但担心如何尝试和编码复杂的关系似乎不那么直接,而是让引擎为您生成它。此外,当关系变得如此复杂时,我倾向于避免尝试使用 EF 生成它,并尝试使用存储过程来更轻松地对可能出现的性能瓶颈进行故障排除。

【讨论】:

  • 我终于得出结论,我也必须走这条路。关键是 edmx 模型允许在概念模型中进行更改,而代码优先不提供任何工具来进行这种区分。使用代码优先,所有映射配置都平等地进入商店模型和概念模型。恐怕 EF 团队对开发工具以仅在代码优先 API 中塑造概念模型(商店模型除外)不感兴趣。
  • 祝你未来好运,MS 取消了对 edmx 的支持...theregister.co.uk/2014/10/23/…
猜你喜欢
  • 2011-07-23
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
  • 2014-07-20
  • 1970-01-01
相关资源
最近更新 更多