实体框架上的多态交叉关联
Posted
技术标签:
【中文标题】实体框架上的多态交叉关联【英文标题】:Polymorphic cross-associations on Entity Framework 【发布时间】:2012-06-30 00:52:41 【问题描述】:好的,这是我要解决的一个有趣且最重要的真正紧迫的问题......为了让其他人清楚地理解它,我已经伸展自己做了一个图文并茂的帖子。
对象模型
所以我想到了这个简单、容易和“漂亮”的模型。看第一张图。 (您可以忽略PathEntry
,这与我的情况无关。)
这个想法是MediaFeedItem
拥有:
ThumbnailFileEntries
的集合(可通过 ThumbnailFiles 属性访问)
最多 1 个原始 FileEntry
(MetadataFile 属性)和
最多 1 个MediaFileEntry
(MediaFile 属性)
我们将这最后三种实体类型称为文件实体。
现在还有更多:如您所见,我从 FileEntry
继承了 ThumbnailFileEntry
和 MediaFileEntry
,我们不要争论!(暂时),它就是其中之一设计的结尾部分以及这两种实体类型将在以后继续增长。
这已经给我带来了一些关于由文件实体到MediaFeedItem
的关系引起的多态关联的重要问题。
您首先要观察的是,我已将导航属性从派生 文件实体(ThumbnailFileEntry
和MediaFileEntry
)消除到主要实体MediaFeedItem
.
我这样做是因为它们已经继承了基类FileEntry
中定义的属性。如您所见,我不会删除这些关联末尾的角色。
关系模型
我将使用概念上非常优越的 TPT 策略来生成我的对象模型并将其映射到 RDB 世界(与 TPH/TPC 相比)。
我正在使用 EF5-rc、EDMX 模型设计器来设计我的模型,并使用 EF5 DbContext Generator 来生成 DbContext 和 POCO,因为我想使用 DbContext API。
如您所见,我可以使用 EF 工具很好地生成数据库模型:
问题
加载新的 MediaFeedItem 并保存时,出现以下错误:
System.InvalidOperationException:违反多重约束。关系“MediaFeedModel.MediaFeedItem_MetadataFile”的角色“MetadataFile”具有多重性 1 或 0..1。
我做错了什么?
【问题讨论】:
只是为了澄清一下,您要添加一个全新的 MediaFeedItem 并收到此错误?能否请您在 SaveChanges 之前断点并告诉我每个导航属性(即 MetadataFile、ThumbnailFiles 和 MediaFile)中的内容 为什么它"nicely" 创建数据库? DB 模式是完全错误的,不是吗?您的架构中存在一对多关系,而您的 EF 模型具有一对一关系……您是如何创建此架构的?使用DbContext
?您是否删除或更改了连接字符串或删除了连接字符串的 EDM 部分并从 OnModelCreating
中删除了 UnintentionalCodeFirstExeception
,即您是否从 Model-First 转换为 Code-First?
另外:“我已经从派生的文件实体中删除了导航属性... 因为 它们已经继承了定义在基类”。这可能不是您的问题的原因,但是:这两个已删除的属性属于与导航不同的关联。基类中的属性。通过删除它们,基本属性不会成为导航。其他两个关联的属性,并且它不会替换已删除的属性。单个导航属性不能属于多个关系。
感谢大家的 cmets,这是加拿大的长周末,嗯.. 我真的需要它。关于您的第一条评论@Slauma,数据库使用 1-* 来实现 1-0..1 (存在 FK 关系,但可以说我没有看到任何阻止除 0..1 之外的多重性的东西DB 结束。)我没有使用 DB 上下文创建模式,正如我所说,我首先使用 EDMX 生成它并使用 EF 向导生成 DB ..然后我生成 DbContext(使用它进行编码)。无论如何,我认为您在第二条评论中对这个问题绝对是正确的。将在下面发表更多评论。
您能否显示最终导致异常的“加载新的 MediaFeedItem 并保存时”的代码?我也很困惑,当您从模型生成架构时,EDMX 中的一对一关系会与数据库中的外键创建一对多关系。
【参考方案1】:
看看你的问题,有一点很突出,File 和 MediaFeedItem 之间的 FK 关系是必需的(即文件必须有 MediaFeedItem),但如果你在 File 的扩展版本中,你可能不想要这个。
我认为您想要做的是以下之一:
将 MediaFeedItem_FileEntry 上的多重性更改为 0..1 - 0..1,这样任何一端都不需要它 创建一个新的扩展类型来处理您的 metadataFile 类型并删除基类型和 MediaFeedItem 之间的直接引用我个人认为第二种方法更优雅地解决了您的问题,因为它为您的 MetadataFile 创建了一个实际类型
似乎正在发生的事情是您正在尝试创建扩展类型,但基本类型实际上并不是元数据文件。
【讨论】:
所以,是的,我听到了你们俩的声音,事实上,很明显,这里的问题是我错误的、原始的假设,即我可以为不同的关系“共享”相同的导航属性.在SaveChanges()
之前闯入这些实体表明,除了添加到图表中的最后一个文件实体 之外,“拥有”MediaFeedItem
已重置为null
。此外,即使保留两个导航属性,也不会设置继承关系,除非我明确这样做。我需要按照建议进行一些重构。以上是关于实体框架上的多态交叉关联的主要内容,如果未能解决你的问题,请参考以下文章