Entity Framework 在 Code First 迁移中进行不正确的 PK-FK 映射
Entity Framework making incorrect PK-FK mapping on Code First migration
我将以下 3 类 设置为使用 Entity Framework Code First 迁移在 SQL 服务器数据库中创建。 调查对象是主要的table。
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;}
}
每个调查可以有多个设备(一对多)
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);
}
问题是,当我应用代码第一次迁移时,进程 table (1-to-0..1) 中的 ForeignKey 属性 一直设置为 ProcessId
字段而不是 SurveyId
。这意味着每次我尝试添加新的 Process 记录时,我都会收到以下错误:
INSERT 语句与 FOREIGN KEY 约束冲突 "FK_Survey.Processes_Survey.Surveys_ProcessId"。冲突发生在数据库 "Backflow"、table "Survey.Surveys"、列 'SurveyId'。
设备的一对多映射工作得很好。
我最初认为这是由于我所有的 PK 字段都只写 Id,但即使添加了附加标签部分,它仍然使 PK-FK 不正确link。我也尝试通过添加 DataAnnotation [Key, ForeignKey("xyz")]
来避免 Fluent API,但结果相同。重新编译项目,重新启动 Visual Studio,甚至创建新项目和新数据库都无济于事。
我在 Fluent API 或 DataAnnotations 中是否缺少某些内容以使其正确加入?此外,手动修复数据库中的 FK 确实可以正常工作 ,但这种做法违背了在 Code First 中通过迁移完成所有操作的目的。
1-0..1关系的流畅映射是正确的:
modelBuilder.Entity<Survey>()
.HasOptional(s => s.Process)
.WithRequired(p => p.Survey);
但是 Process
不应该有 SurveyID
属性(和列)。在 EF6 中,1-0..1 关系的 dependent 部分(此处:Process
)应该有一个主键,该主键也引用其 principal(此处:Survey
)作为外键。所以 Process.ProcessID
既是主键又是外键。因此,一个 Process
唯一地绑定到一个 Survey
.
顺便说一句,在其他映射中,我还要提到外键:如果选择配置而不是约定,最好是完整的。
modelBuilder.Entity<Survey>()
.HasMany(s => s.Devices)
.WithRequired(d => d.Survey)
.HasForeignKey(d => d.SurveyId);
我将以下 3 类 设置为使用 Entity Framework Code First 迁移在 SQL 服务器数据库中创建。 调查对象是主要的table。
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;}
}
每个调查可以有多个设备(一对多)
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);
}
问题是,当我应用代码第一次迁移时,进程 table (1-to-0..1) 中的 ForeignKey 属性 一直设置为 ProcessId
字段而不是 SurveyId
。这意味着每次我尝试添加新的 Process 记录时,我都会收到以下错误:
INSERT 语句与 FOREIGN KEY 约束冲突 "FK_Survey.Processes_Survey.Surveys_ProcessId"。冲突发生在数据库 "Backflow"、table "Survey.Surveys"、列 'SurveyId'。
设备的一对多映射工作得很好。
我最初认为这是由于我所有的 PK 字段都只写 Id,但即使添加了附加标签部分,它仍然使 PK-FK 不正确link。我也尝试通过添加 DataAnnotation [Key, ForeignKey("xyz")]
来避免 Fluent API,但结果相同。重新编译项目,重新启动 Visual Studio,甚至创建新项目和新数据库都无济于事。
我在 Fluent API 或 DataAnnotations 中是否缺少某些内容以使其正确加入?此外,手动修复数据库中的 FK 确实可以正常工作 ,但这种做法违背了在 Code First 中通过迁移完成所有操作的目的。
1-0..1关系的流畅映射是正确的:
modelBuilder.Entity<Survey>()
.HasOptional(s => s.Process)
.WithRequired(p => p.Survey);
但是 Process
不应该有 SurveyID
属性(和列)。在 EF6 中,1-0..1 关系的 dependent 部分(此处:Process
)应该有一个主键,该主键也引用其 principal(此处:Survey
)作为外键。所以 Process.ProcessID
既是主键又是外键。因此,一个 Process
唯一地绑定到一个 Survey
.
顺便说一句,在其他映射中,我还要提到外键:如果选择配置而不是约定,最好是完整的。
modelBuilder.Entity<Survey>()
.HasMany(s => s.Devices)
.WithRequired(d => d.Survey)
.HasForeignKey(d => d.SurveyId);