Tom*_*rek 14 c# entity-framework fluent-entity-framework
我在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);
}
}
Run Code Online (Sandbox Code Playgroud)
当我启动这段代码时,我得到了正确的表格结构:
dbo.Contacts
Id (PK)
Student_Id (FK, NULL, CASCADE ON DELETE)
dbo.Students
Id (PK)
Run Code Online (Sandbox Code Playgroud)
但是,现在我想添加Student_Id
要在Contact
实体中可用的属性.所以我可以阅读,Student_Id
而无需通过.Student.Id
导航加入其他表.
如果我的属性添加到Contact
实体,我最终要么有两列Student_Id
和Student_Id1
,或者我结束了一个错误信息说Each property name in a type must be unique.
.
该列已经在数据库中,我需要的只是将它放在实体中,为什么这么麻烦?有解决方案吗?
Tom*_*rek 12
在向GitHub询问后,我设法得到了实体框架项目经理的回复.
不幸的是,这是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; }
}
Run Code Online (Sandbox Code Playgroud)
但我认为这不是你想要的.所以,我认为你有三个选择:
根据我的经验,最后一个是你想要实现的最多调整(但这是我的意见).在这种情况下,您可以根据需要使用Fk属性,唯一需要通过集合更改Contact
导航属性Student
(或省略此nav.属性并创建单向关系):
public class Student
{
public int Id { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
配置将是这样的:
builder.Entity<Contact>()
.HasOptional(x => x.Student)
.WithMany(x => x.Contacts)
.HasForeignKey(x => x.StudentId)
.WillCascadeOnDelete(true);
Run Code Online (Sandbox Code Playgroud)
第四个选项可以创建两个单向关系:
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);
Run Code Online (Sandbox Code Playgroud)
但是这个选项打破了两个表之间的真实关系.