【问题标题】:Entity Framework 4.1 Code First Foreign Key Id's实体框架 4.1 代码优先外键 ID
【发布时间】:2011-08-05 02:20:19
【问题描述】:

我有两个实体被一对多引用。当实体框架创建表时,它会创建两个外键,一个用于我使用 fluent 接口指定的键,另一个用于 ICollection。如何摆脱重复的外键?

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);
}

谢谢!

【问题讨论】:

    标签: c# poco entity-framework-4.1


    【解决方案1】:

    您必须明确指定关联的多端:

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

    否则 EF 将假定存在两种关联:一种未在 Department 中公开,具有外键 DepartmentIdPerson 类中的导航属性 Department,正如您在 Fluent 代码中定义的那样 -和另一个关联,它属于暴露的导航属性People,但在Person 中有另一个未暴露的结尾,以及由 EF 自动创建的外键。这是您在数据库中看到的另一个键。

    【讨论】:

    • 这可行吗? : [ForeignKey("Department")] public long DepartmentId { get;放; }
    • @billy:这不是 100% 相同,因为注释不会禁用级联删除。如果您不想禁用级联删除,那么它可以工作,是的。但是你甚至不需要注释,因为命名约定会自动检测外键属性。
    【解决方案2】:

    默认的 Code First 约定会检测您的 DepartmentId 外键,因为它是约定俗成的。我认为您应该删除 Fluent 定义:

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 我尝试了这种方法,但在运行Seed() 方法时导致异常,引用默认列名而不是MapKey() 中指定的列名。
      猜你喜欢
      • 2011-08-05
      • 1970-01-01
      • 1970-01-01
      • 2012-05-10
      • 2015-02-24
      • 2021-01-05
      • 1970-01-01
      相关资源
      最近更新 更多