2011-04-13 74 views
18

我有两个实体引用一对多。当实体框架创建表时,它会创建两个外键,一个用于我用流畅界面指定的键,另一个用于ICollection。我如何摆脱重复的外键?实体框架4.1代码第一外键ID的

public class Person 
{ 
    public long RecordId { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string Email { get; set; } 
    public string Username { get; set; } 

    public long DepartmentId { get; set; } 
    public virtual Department Department { get; set; } 
} 

public class Department 
{ 
    public long RecordId { get; set; } 
    public string Name { get; set; } 

    public virtual ICollection<Person> People { get; set; } 
} 

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<Person>() 
     .HasRequired(p => p.Department) 
     .WithMany() 
     .HasForeignKey(p => p.DepartmentId) 
     .WillCascadeOnDelete(false); 
} 

谢谢!

回答

25

您必须指定该协会明确地的许多高端:

modelBuilder.Entity<Person>() 
    .HasRequired(p => p.Department) 
    .WithMany(d => d.People) 
    .HasForeignKey(p => p.DepartmentId) 
    .WillCascadeOnDelete(false); 

否则EF假定有两个协会:一个不暴露Department与外键DepartmentId和导航属性DepartmentPerson类中,如您在Fluent代码中定义的那样 - 另一个关联属于已公开的导航属性People但是另一个未公开的末端在Person和由EF自动创建的外键。这是您在数据库中看到的另一个关键。

+0

可以这样工作吗? : [ForeignKey(“Department”)] public long DepartmentId {get;组; } – billy 2012-03-16 14:40:22

+0

@billy:这不是100%相同,因为注释不会禁用级联删除。如果你不想禁用级联删除,那么它的工作,是的。但是你甚至不需要注释,因为命名约定会自动检测外键属性。 – Slauma 2012-03-16 14:50:50

+0

超级,谢谢! – billy 2012-03-16 15:30:18

6

默认的Code First约定会检测您的DepartmentId外键,因为它是传统的。我想你应该删除流利的定义:

modelBuilder.Entity<Person>() 
    .HasRequired(p => p.Department) 
    .WithMany() 
    .WillCascadeOnDelete(false); 
3

最好的办法是从Person类中删除detamentid属性并添加以下语句。 MapKey将创建您指定的名称的外键列

modelBuilder.Entity<Person>().HasRequired(p => p.Department) 
    .WithMany().Map(x=>x.MapKey("DepartmentId")) 
    .WillCascadeOnDelete(false); 
+0

我试过这种方法,但是在运行'Seed()'方法时引发了一个异常,引用了默认的列名,而不是'MapKey()'中指定的那个。 – 2013-10-30 22:24:06

相关问题