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

Ger*_*old 18 c# foreign-keys ef-code-first ef-database-first entity-framework-5

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

在此输入图像描述

两者Event,PersonProduct在评论中有记录.如您所见,没有严格的FK约束.

在实体框架可以通过sublassing支持这种模式Comment进入EventComment等,让EventEventComments收集等:

在此输入图像描述

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

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

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

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

外键组件"OwnerId"不是"EventComment"类型的声明属性.验证它是否未从模型中明确排除,并且它是有效的原始属性.

当我有双向关联并被OwnerId映射为属性时会发生这种情况Comment.我的EventMapclass(EntityTypeConfiguration<Event>)中的映射如下所示:

this.HasMany(x => x.Comments).WithRequired(c => c.Event)
    .HasForeignKey(c => c.OwnerId);
Run Code Online (Sandbox Code Playgroud)

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

this.HasMany(x => x.Comments).WithRequired().Map(m => m.MapKey("OwnerId"));
Run Code Online (Sandbox Code Playgroud)

这引发了一个 MetaDataException

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

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

更多细节:

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

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

小智 1

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