如何建立一对一的关系,双方的关系是可选的

时间:2015-11-26 10:27:01

标签: .net sql-server asp.net-mvc entity-framework

是否可以在两个实体之间创建关系,其中每个实体都有另一个外键,外键字段也是可选的?我尝试根据以下代码创建表:

public class Museum
{
    public int MuseumId { get; set; }
    public string Name { get; set; }

    [ForeignKey("Curator")]
    public int? CuratorId { get; set; }
    public virtual Curator Curator { get; set; }
}

public class Curator
{
    public int CuratorId { get; set; }
    public string Name { get; set; }

    [ForeignKey("Museum")]
    public int? MuseumId { get; set; }
    public virtual Museum Museum { get; set; }
}

但是我收到以下错误:

  

Curator_Museum_Target :: Multiplicity在关系'Curator_Museum'中的角色'Curator_Museum_Target'中无效。由于Dependent Role属性不是关键属性,因此Dependent Role的多重性的上限必须为'*'。

有没有办法解决这个问题?

2 个答案:

答案 0 :(得分:0)

您无法在数据库中执行此操作。 FK必须引用关系另一侧的PK。 PK不能是可选的。例如,您希望在表AB之间实现的关系具有以下条件:

  • 如果A.Id是与B.Id相关的FK,则B.Id必须是PK,因此,不是可选的
  • 反之,如果B.Id是与A.Id相关的FK,A.Id必须是PK,因此,不是可选的

所以,这不是EF的问题,而是你的模型的问题。

要模拟这个,你可以使用桥牌表,像这样" pseducode":

[Table: ABBridge]
AId not null
BId not null

因此,如果存在AB的依赖关系,或者反之,则只需在此表中添加一个条目即可。它没有这样的关系,这个表中没有字段。 AIdBId都应该是桥接表的PK。

这将是一个多对多的关系。如果您使用的是现代版本的EF(6.1或更高版本),则可以通过使用{{3}使AIdBId唯一,将其一对一转换为一对一在他们两个。

[Index("AIdUniqueIndex", IsUnique = true)]
public int AId { get; set; }
[Index("BIdUniqueIndex", IsUnique = true)]
public int AId { get; set; }

如果您使用的是旧版本,则应使用业务逻辑来确保这一点。

答案 1 :(得分:0)

您可以使用模型构建器的流畅API来配置它。

对于可选的1:1关系,代码为:

ModelBuilder.Entity<Museum>().HasOptional(x => x.Curator).WithOptionalPrincipal(x => x.Museum).WillCascadeOnDelete(true);

正如JotaBe所指出的,当将此配置映射到数据库时,EF不会在两个表中创建外键列。相反,仅为HasOptional()子句中定义的一侧创建FK列。主/唯一键基表将配置为WithOptionalPrincipal()。

对于示例代码,DB上的FK约束将在Curator表中创建为Curator.Museum_Id - &gt;博物馆.Id,博物馆作为主要/唯一关键基准表。

另请注意,上面给出的代码将cascade delte配置为&#34;如果博物馆被删除,则删除馆长&#34;。