我有实体 Contact 必须链接到它自己,而不是在分层模式中
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
申报了属性(property)类(class)。现在我正在尝试设置关系,但这不起作用,我觉得我不知道如何正确设置它。请指教?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);
}
}
最佳答案
当您使用主键作为关系的外键时,关系不能是可选的,因为主键不能有 NULL
值。外键将始终具有值 - 比如说 ( ContactId
= 1, AgentId
= 2) - 如果具有 ( AgentId
= 1, ContactId
= 2) 的行没有违反外键约束存在。
但是对于必需的关系,您只能拥有成对的行,并且根本不可能将任何有意义的行插入到数据库表中,因为它总是会违反外键约束:插入行 ( AgentId
= 1, ContactId
= 2) 行 ( AgentId
= 2, ContactId
= 1) 必须存在,反之亦然。您可以插入的唯一可能的行是这样的行 (AgentId
= 1, ContactId
= 1),即 Opposite
contact 是联系人本身。
为了实现可选关系,您需要单独的外键:
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 方面,您不能使其成为一对一的关系。您只能在数据库中的复合外键上添加唯一索引,以确保没有两个联系人具有相同的对立面。
关于entity-framework - Entity Framework : create one-to-one relation to itself,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14424172/