首页 文章

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

提问于
浏览
17

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

enter image description here

EventPersonProduct 都在Comment中有记录 . 如您所见,没有严格的FK约束 .

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

enter image description here

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

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

好 . 现在我们想要转向代码优先 . 所以我开始将数据库逆向工程化为代码优先模型(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模型("code second") . (这将是暂时的解决方法) .

  • 当我将工作代码优先模型(带有一个关联)导出到edmx( EdmxWriter )时,关联似乎在存储模型中,而在原始edmx中,它们是概念模型的一部分 .

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

1 回答

  • 1

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

相关问题