实体框架在Code First迁移中制作错误的PK-FK映射

时间:2017-03-09 21:05:30

标签: ef-code-first entity-framework-6 ef-fluent-api

我使用Entity Framework Code First迁移设置了在SQL Server数据库中创建的以下3个类。 调查对象是主表。

public class Survey
{
    public int SurveyId {get; set;} //Primary Key
    public string Description {get; set;}
    public bool HasDevice {get; set;}
    public bool HasProcess {get; set;}

    public virtual Process Process {get; set;} 
    public virtual ICollection<Device> Devices {get; set;} 
}

每次调查都可以有多个设备(1对多)

public class Device
{
    public int DeviceId {get; set;} //Primary Key
    public string DeviceType {get; set;}

    public int SurveyId {get; set;} //Foreign Key
    public virtual Survey Survey {get; set;}
}

每项调查只应有一个流程(1到0..1)

public class Process
{
    public int ProcessId {get; set;} //Primary Key
    public string ProcessInfo {get; set;}

    public int SurveyId {get; set;} //Foreign Key
    public virtual Survey Survey {get; set;}
}

这些类的Fluent API映射如下所示。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.HasDefaultSchema("Survey");
    modelBuilder.Entity<Survey>().HasOptional(x => x.Process).WithRequired(x => x.Survey);
    modelBuilder.Entity<Survey>().HasMany(x => x.Devices).WithRequired(x => x.Survey);
}

问题在于,当我首先应用代码迁移时,Process表中的ForeignKey属性(1到0..1)会一直设置为ProcessId字段而不是SurveyId }。这意味着每次我尝试添加新的Process记录时,都会出现以下错误:

INSERT语句与FOREIGN KEY约束“FK_Survey.Processes_Survey.Surveys_ProcessId”冲突。冲突发生在数据库“Backflow”,表“Survey.Surveys”,列“SurveyId”。

Device的1对多映射工作正常。

我最初认为这是因为我的所有PK字段都只是说 Id ,但即使添加了额外的标签部分,它仍会产生错误的PK-FK链接。我也尝试通过添加DataAnnotation [Key, ForeignKey("xyz")]来避免使用Fluent API,但它具有相同的结果。重新编译项目,重新启动Visual Studio,甚至创建新项目和新数据库都无济于事。

Fluent API或DataAnnotations中是否存在我无法正确连接的内容?此外,手动修复数据库中的FK确实可以使其正常工作,但这种做法违背了使用迁移在Code First中执行所有操作的目的。

1 个答案:

答案 0 :(得分:3)

1-0..1关系的流畅映射是正确的:

modelBuilder.Entity<Survey>()
    .HasOptional(s => s.Process)
    .WithRequired(p => p.Survey);

但是Process不应该有SurveyID属性(和列)。在EF6中,1-0..1关系的依赖部分(此处为:Process)应该具有一个主键,该主键也引用其主体(此处:Survey)作为外键。所以Process.ProcessID既是主键,也是外键。因此,一个ProcessSurvey唯一关联。

顺便说一下,在另一个映射中,我还会提到外键:如果选择的配置超过约定,那么最好完成。

modelBuilder.Entity<Survey>()
    .HasMany(s => s.Devices)
    .WithRequired(d => d.Survey)
    .HasForeignKey(d => d.SurveyId);