在HasOptional()中映射外键。entity framework6中的WithOptionalDependent()关系

我在Entity Framework 6.1.3中有以下数据模型:

using System.Data.Entity; public class Student { public int Id { get; set; } public virtual Contact Contact { get; set; } } public class Contact { public int Id { get; set; } public virtual Student Student { get; set; } } public class MyContext : DbContext { protected override void OnModelCreating(DbModelBuilder builder) { builder.Entity() .HasOptional(x => x.Student) .WithOptionalDependent(x => x.Contact) .WillCascadeOnDelete(true); } } public static class Program { private static void Main() { Database.SetInitializer(new DropCreateDatabaseAlways()); using (var context = new MyContext()) context.Database.Initialize(force: true); } } 

当我启动此代码时,我得到了正确的表格结构:

 dbo.Contacts Id (PK) Student_Id (FK, NULL, CASCADE ON DELETE) dbo.Students Id (PK) 

但是,现在我想添加Student_Id属性以在Contact实体中可用。 所以我可以阅读Student_Id而无需通过.Student.Id导航加入其他表。

如果我将该属性添加到Contact实体,我最终Student_Id两列Student_IdStudent_Id1 ,或者我最后会收到一条错误消息,指出Each property name in a type must be unique.

该列已经在数据库中了,我所需要的只是将它放在实体中,为什么这么麻烦呢? 有解决方案吗?

在向GitHub询问后,我设法得到了entity framework项目经理的回复。

不幸的是,这是EF6的限制。 您不能以一对一的关系拥有外键属性,除非它也是主键属性。 这主要是因为EF6不支持备用键/唯一索引,因此您无法强制非主键属性是唯一的。 当外键属性不在实体中时,你可以这样做的事实有点怪癖……但显然不是我们要删除的东西😄。

EF Core支持BTW备用密钥(因此也支持此方案)。

– Rowan Miller @ https://github.com/aspnet/EntityFramework6/issues/159#issuecomment-274889438

如果你想以一对一的关系在依赖实体中声明FK属性,我恐怕你也必须将它用作PK。 EF Code First 要求依赖实体的PK也必须是关系的FK:

 public class Contact { [Key,ForeignKey("Student")] public int StudentId { get; set; } public virtual Student Student { get; set; } } 

但我认为这不是你想要的。 所以,我认为你有三个选择:

  • 您保留当前的关系配置。
  • 创建真实的一对一关系 。
  • 创建一对多的关系

根据我的经验,最后一个是你想要实现的最多调整(但这是我的意见)。 在这种情况下,您可以根据需要使用Fk属性,唯一需要通过集合更改Student上的Contact导航属性(或省略此nav。属性并创建单向关系):

 public class Student { public int Id { get; set; } public virtual ICollection Contacts { get; set; } } 

配置将是这样的:

  builder.Entity() .HasOptional(x => x.Student) .WithMany(x => x.Contacts) .HasForeignKey(x => x.StudentId) .WillCascadeOnDelete(true); 

更新

第四个选项可以创建两个单向关系:

  builder.Entity() .HasOptional(x => x.Student) .WithMany() .HasForeignKey(x => x.StudentId) .WillCascadeOnDelete(true); builder.Entity() .HasOptional(x => x.Contact) .WithMany() .HasForeignKey(x => x.ContactId) .WillCascadeOnDelete(true); 

但是这个选项打破了两个表之间的真实关系。