建模多态关联数据库优先与代码优先

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

在此处输入图像描述

EventPersonProduct都有评论记录。 如您所见,没有严格的FK约束。

在Entity Framework中,可以通过将Comment化为EventComment等来支持这个模型,并让Event有一个EventComments集合等:

在此处输入图像描述

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

这是数据库优先的。 我们的现实模型就像这样,没问题。

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

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

外键组件“OwnerId”不是“EventComment”类型的声明属性。 validation它是否未从模型中明确排除,并且它是有效的原始属性。

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

 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中,它们是概念模型的一部分。

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

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