EF4.1:可能有零或一到零或一(0..1到0..1)的关系?

时间:2011-06-23 14:23:24

标签: sql-server entity-framework sql-server-2008 entity-framework-4.1

带有SQL Server 2008 R2的.NET 4.0。我试图表示0..1到0..1的关系,我不断收到以下错误:

  

错误113:多重性与关系“{1}”中角色“{0}”中的引用约束冲突。由于Dependent Role中的所有属性都是不可为空的,因此Principal Role的多重性必须为“1”。

即使依赖实体中的属性可以为空,我也会收到此消息。是否有可能在实体框架中表示这种关系?

何时可能发生这种情况(与数据库设计是否良好无关)的一个例子是当您有一个自身存在的请求时,一旦请求完成就会与之关联的结果,以及请求最终被修剪,但结果仍然存在。

3 个答案:

答案 0 :(得分:2)

不,这是不可能的,我怀疑它在SQL服务器中是否有效。数据库关系要求一端变得依赖。这意味着它引用了主端的主键(PK) - 我们称之为外键(FK)。如果我们谈论一对一关系,则必须将FK标记为唯一,以便从属表中只有一个记录可以从主表中引用给定记录。在这种情况下,唯一有效的关系是0..1 - 1,其中principal可以不依赖而存在,但依赖只能在与现有主体相关时才存在,因为它的FK值必须设置为主体的PK值。从理论上讲,FK可以为空,但它取决于数据库如何实现唯一约束的方式。如果数据库将null计为另一个唯一值,则只有一个依赖记录可以将FK设置为​​null(我认为这是SQL服务器的情况)。

在EF中,这更复杂,因为EF不支持唯一约束,因此只有当依赖实体中的FK也是它的PK时,你才可以建立一对一关系(=无法将其设置为null )。如果你不能将FK设置为​​null,则不能将其置为可空,并且因为该主体实体必须存在,否则引用完整性将引发错误。

最适合您的解决方案是将Request视为主要实体,将Result视为依赖实体。必须首先创建请求,并且只要Result,就必须将其保留在数据库中。 Result必须具有相同的PK值(列不能自动递增)作为相应的Request(并且PK必须是FK到Request)。

答案 1 :(得分:1)

这可以通过SQL 2008的多种方式实现(例如,筛选索引,计算列的约束),并且是SQL 2012中唯一索引的默认功能。

根据ANSI标准SQL:92,SQL:1999和SQL:2003,UNIQUE约束应该禁止重复的非NULL值,但允许多个NULL值。 SQL对此的支持有点近,但不是非标准的。

请注意,正如0..1到多个关系可以具有零并且仍然被视为具有从属列,因此0..1到0..1关系也是如此。

请注意,EF5(这比Ladislav的答案更新)也支持这一点,但依赖的方向取决于设计中设置0..1的顺序,如果您使用的是模型-第一。但是,它似乎仍然是确定性的。

答案 2 :(得分:0)

是的,有一种方法可以做你想要的:制作另一个表的两个表子类型。这意味着同步它们的PK值,以便一个表的PK值等于另一个表中的相应PK值。例如,如果两个表都有单独的identity列,则它们都必须更改为常规列,其他地方生成identity,然后当两个表都有一个时,两个表中使用相同的值一对一的关系。

也就是说,创建一个超类型或“master”表,其中包含PK值,该值可选择在其他两个表中的每一个中一次。使两个表的键列既是该表的CLUSTERED PK,又一个FK到主表,而不是其他子类表。

问题解决了。这些表可以包含每个值的零行或一行。

最终,如果PK生成不是基于身份的,并且除了PK值之外没有数据存储在超类型表中,那么实际上并不真正需要超类型表,除非明确记录该值。逻辑实体存在(它在超类型表中)但在两个子类型表中都有零行。如果缺少该值足以可靠地指示两个子类型表都具有零行,并且可以在没有标识列的情况下生成两个表的PK值,则可以处理超类型表。实际上不需要两个表之间的FK,因为任何一个表都不允许行与另一个表中的当前行匹配。