4

我有实体联系人必须链接到自身而不是分层模式

public partial class Contact 
{
  [Key, Column(Order = 0)]
  public int AgentId { get; set; }
  [Key, Column(Order = 1)]
  public int ContactId { get; set; }
  public virtual Contact Opposite { get; set; }
  public ..... many other properties
}

每个联系人都有相反的Contact链接ON c1.AgentId = c2.ContactId AND c1.ContactId = c2.AgentId。相反的接触是可选的,但当它存在时,它们是一对一的。不是亲子。此关系的名称必须是Opposite。我已经在Contact课堂上声明了财产。现在我正在尝试设置关系,但这不起作用,我觉得我不知道如何正确设置它。请指教?

public class EFDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        Action<ForeignKeyAssociationMappingConfiguration> mapKey = x => x.MapKey("ContactId", "AgentId");
        modelBuilder.Entity<Contact>().HasOptional<Contact>(c => c.Opposite).WithRequired().Map(mapKey);
    }
}
4

1 回答 1

2

当您使用主键作为关系的外键时,该关系不能是可选的,因为主键不能有NULL值。外键将始终具有值 - 例如 ( ContactId= 1, = 2) - 如果 ( = 1, = 2) 的行不存在AgentId,则外键约束将被违反。AgentIdContactId

但是对于必需的关系,您只能有成对的行,并且根本不可能将任何有意义的行插入到数据库表中,因为它总是会违反外键约束:要插入行(AgentId= 1,ContactId= 2)行(AgentId= 2, ContactId= 1) 必须存在,反之亦然。您可以插入的唯一可能的行是(AgentId= 1,ContactId= 1)之类的行,即Opposite联系人是联系人本身。

为了实现可选关系,您需要单独的外键:

public partial class Contact 
{
    [Key, Column(Order = 0)]
    public int AgentId { get; set; }
    [Key, Column(Order = 1)]
    public int ContactId { get; set; }

    [ForeignKey("Opposite"), Column(Order = 2)]
    public int? OppositeContactId { get; set; }
    [ForeignKey("Opposite"), Column(Order = 3)]
    public int? OppositeAgentId { get; set; }

    public virtual Contact Opposite { get; set; }

    //...
}

这是一对多的关系。使用 Fluent API 而不是数据注释,它将是:

modelBuilder.Entity<Contact>()
    .HasOptional(c => c.Opposite)
    .WithMany()
    .HasForeignKey(c => new { c.OppositeContactId, c.OppositeAgentId });

在 EF 方面,您不能使其成为一对一的关系。您只能在数据库中的复合外键上添加唯一索引,以确保没有两个联系人具有相同的对立面。

于 2013-01-20T14:08:09.963 回答