如何让EF模型生成含PK与FK的SQL Server迁移,实现复合主键关联?
问题:Entity Framework生成关联表迁移不符合预期(PK/FK定义问题)
尝试在SQL Server中通过Entity Framework生成包含主键(PK)和外键(FK)的关联表,但迁移生成的表结构不符合预期,需明确PK/FK定义逻辑并解决问题。
现有代码
AtaRegistroPrecoModel
namespace ContratosMVC.Models { public class AtaRegistroPrecoModel { public int Id { get; set; } public DateTime Data { get; set; } public short Numero { get; set; } public short Ano { get; set; } public string? Objeto { get; set; } public string? Observacao { get; set; } public DateTime DataInicio { get; set; } public DateTime DataFim { get; set; } public string? Arquivo { get; set; } public DateTime DataCriacao { get; set; } public ContratoModel? Contrato_ { get; set; } public ProcessoModel? Processo_ { get; set; } public CorrespondenciaModel? Correspondencia_ { get; set; } } }
AtaRegistroPrecoFornecedorModel及配置类
namespace ContratosMVC.Models { public class AtaRegistroPrecoFornecedorModel { [Required, Key, ForeignKey("AtaRegistraPrecoFornecedor_Fornecedor_Id")] public AtaRegistroPrecoModel AtaRegistraPrecoFornecedor_Fornecedor_ { get; set; } [Required, Key] public FornecedorModel Fornecedores_ { get; set; } } public class AtaRegistroPrecoFornecedorMap : IEntityTypeConfiguration<AtaRegistroPrecoFornecedorModel> { public void Configure(EntityTypeBuilder<AtaRegistroPrecoFornecedorModel> builder) { builder.HasNoKey(); } } }
当前生成的表结构

期望的表结构

问题分析与解决方案
核心错误点
- 直接将导航属性标记为
[Key]:EF无法将导航属性直接作为主键,需要显式定义对应的外键字段 - 配置类中调用
builder.HasNoKey():这会让EF将该实体识别为无键类型,完全无法生成主键约束 ForeignKey特性参数错误:参数应指向存在的外键字段,而非自定义的无效名称
正确代码实现
修改关联实体类
namespace ContratosMVC.Models { public class AtaRegistroPrecoFornecedorModel { // 复合主键字段,同时作为外键 public int AtaRegistroPrecoId { get; set; } public int FornecedorId { get; set; } // 导航属性,通过ForeignKey关联到对应外键字段 [ForeignKey(nameof(AtaRegistroPrecoId))] public AtaRegistroPrecoModel AtaRegistroPreco { get; set; } = null!; [ForeignKey(nameof(FornecedorId))] public FornecedorModel Fornecedor { get; set; } = null!; } }
修改配置类(Fluent API设置复合主键与外键)
namespace ContratosMVC.Models { public class AtaRegistroPrecoFornecedorMap : IEntityTypeConfiguration<AtaRegistroPrecoFornecedorModel> { public void Configure(EntityTypeBuilder<AtaRegistroPrecoFornecedorModel> builder) { // 设置复合主键:由两个外键字段共同组成 builder.HasKey(arpf => new { arpf.AtaRegistroPrecoId, arpf.FornecedorId }); // 显式配置外键关联(可选,EF可自动识别,但显式配置更清晰) builder.HasOne(arpf => arpf.AtaRegistroPreco) .WithMany() // 若AtaRegistroPrecoModel中有对应集合导航属性,替换为属性名,如.WithMany(arp => arp.Fornecedores) .HasForeignKey(arpf => arpf.AtaRegistroPrecoId) .OnDelete(DeleteBehavior.Restrict); // 根据业务需求设置删除行为 builder.HasOne(arpf => arpf.Fornecedor) .WithMany() // 同理,若FornecedorModel有对应集合导航属性,替换为属性名 .HasForeignKey(arpf => arpf.FornecedorId) .OnDelete(DeleteBehavior.Restrict); } } }
PK/FK定义逻辑说明
- 复合主键:多对多关联表的主键必须由两个关联实体的外键字段组成,确保每条关联记录唯一,避免重复关联
- 外键字段:外键字段类型需与关联实体的主键类型严格匹配(如
AtaRegistroPrecoModel主键为int,外键字段也用int) - 导航属性与外键关联:通过
ForeignKey特性或Fluent API将导航属性绑定到对应的外键字段,EF才能正确识别关联关系 - 禁用无键配置:绝对不能使用
HasNoKey(),否则EF会忽略主键约束的生成,导致表结构不符合预期
内容的提问来源于stack exchange,提问作者MatheuS
相关产品推荐
相关产品推荐

