【问题标题】:Entity Framework: create one-to-one relation to itself实体框架:创建与自身的一对一关系
【发布时间】:2013-01-20 11:46:02
【问题描述】:

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

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);
    }
}

【问题讨论】:

  • 请编辑您的问题并添加信息究竟是什么“不工作”。你对你的代码有什么期望,实际发生了什么,你看到了什么错误消息/堆栈跟踪?您尝试过什么来解决问题?
  • 好吧,我尝试过的事情是随机且毫无意义的,我离“不工作”的解决方案还很远。我根本没有任何解决方案可以展示。让我简化一下我的问题:如何根据我的要求将该 Contact 类绑定到自身?

标签: entity-framework ef-code-first code-first


【解决方案1】:

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

但是对于必需的关系,您只能有成对的行,并且根本不可能将任何有意义的行插入到数据库表中,因为它总是会违反外键约束:插入行 (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 方面,您不能使其成为一对一的关系。您只能在数据库中的复合外键上添加唯一索引,以确保没有两个联系人具有相同的对立面。

【讨论】:

  • 谢谢!非常有用的输入
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-01
  • 2016-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多