我在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<Contact>()
.HasOptional(x => x.Student)
.WithOptionalDependent(x => x.Contact)
.WillCascadeOnDelete(true);
}
}
public static class Program
{
private static void Main()
{
Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());
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_Id1
,或者最终会收到一条错误消息Each property name in a type must be unique.
该列已经在数据库中了,我所需要的只是将它放在实体中,为什么这么麻烦?有解决方案吗?
答案 0 :(得分:12)
我设法在asking on GitHub之后得到了实体框架计划经理的回复。
不幸的是,这是EF6的限制。您不能以一对一的关系拥有外键属性,除非它也是主键属性。这主要是因为EF6不支持备用键/唯一索引,因此您无法强制非主键属性是唯一的。当外键属性不在实体中时你可以这样做的事实有点怪癖......但显然不是我们要删除的东西。
EF Core支持BTW备用密钥(因此这种情况)。
- 罗文米勒@ https://github.com/aspnet/EntityFramework6/issues/159#issuecomment-274889438
答案 1 :(得分:8)
如果你想以一对一的关系在依赖实体中声明FK属性,我恐怕你也必须把它当作PK。 EF Code First requires,依赖实体的PK也必须是关系的FK:
Contact
但我认为这不是你想要的。所以,我认为你有三个选择:
根据我的经验,最后一个是你想要实现的最多调整(但这是我的意见)。在这种情况下,您可以根据需要使用Fk属性,唯一需要通过集合更改Student
上的public class Student
{
public int Id { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
}
导航属性(或省略此nav。属性并创建单向关系) ):
builder.Entity<Contact>()
.HasOptional(x => x.Student)
.WithMany(x => x.Contacts)
.HasForeignKey(x => x.StudentId)
.WillCascadeOnDelete(true);
配置就是这样:
builder.Entity<Contact>()
.HasOptional(x => x.Student)
.WithMany()
.HasForeignKey(x => x.StudentId)
.WillCascadeOnDelete(true);
builder.Entity<Student>()
.HasOptional(x => x.Contact)
.WithMany()
.HasForeignKey(x => x.ContactId)
.WillCascadeOnDelete(true);
第四个选项可以创建两个单向关系:
{{1}}
但是这个选项打破了两个表之间的真实关系。