Entity Framework Core “实体类型‘XXX’需要定义一个主键。”

Posted

技术标签:

【中文标题】Entity Framework Core “实体类型‘XXX’需要定义一个主键。”【英文标题】:Entity Framework Core "The entity type 'XXX' requires a primary key to be defined." 【发布时间】:2017-11-23 18:20:22 【问题描述】:

因此,我目前正在尝试使用 Entity Framework Core 创建一个代码优先迁移,用于显示应用程序用户已完成的讲座的表格。我的模型如下所示:

public class LectureCompletion

    [Key,  Column(Order = 0)]
    [ForeignKey("Lecture")]
    public Lecture LectureId  get; set; 

    [Key,  Column(Order = 1)]
    [ForeignKey("User")]
    public ApplicationUser UserId get; set; 

    public bool Completed  get; set; 

我想使用UserIdLectureId 作为唯一的复合键。但是我收到此错误:

实体类型“LectureCompletion”需要定义一个主键。

我不明白为什么会发生这种情况,因为我的关键属性显然位于正确的位置?我可以使用ApplicationUser 作为外键/主键吗?

这是我的Lecture 模型:

public class Lecture

    [Key]
    public int LectureId  get; set; 

    public string ModuleName  get; set; 
    public string LectureName  get; set; 

还有我的ApplicationDBContext.cs

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>

    public DbSet<Lecture> Lectures  get; set; 
    public DbSet<LectureCompletion> LectureCompletion  get; set; 

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    
    

    protected override void OnModelCreating(ModelBuilder builder)
    
        base.OnModelCreating(builder);
        // Customize the ASP.NET Identity model and override the defaults if needed.
        // For example, you can rename the ASP.NET Identity table names and more.
        // Add your customizations after calling base.OnModelCreating(builder);
    

【问题讨论】:

【参考方案1】:

您不能单独使用数据注释来定义复合键。您需要改用 Fluent API。

public class LectureCompletion

    // which is your case.
    [ForeignKey(nameof(Lecture))] 
    public int LectureId  get;set; 
    public Lecture Lecture  get; set; 
    [ForeignKey(nameof(ApplicationUser))]
    public int UserId get;set;
    public ApplicationUser ApplicationUser  get; set; 
    public bool Completed  get; set; 



protected override void OnModelCreating(ModelBuilder builder)

     base.OnModelCreating(builder);

     // Define composite key.
     builder.Entity<LectureCompletion>()
         .HasKey(lc => new  lc.LectureId, lc.UserId );

https://docs.microsoft.com/en-us/ef/core/modeling/keys

【讨论】:

太棒了!谢谢!阅读您提供的链接,这很有效并学到了一些东西。只是想补充一点,外键 UserId 需要是字符串而不是 int。 即使采用这种结构,在加载child的children(二级)时也会出现错误【参考方案2】:

LectureCompletion 类需要正确定义主键。[Key] 是主键注释,用于明确告诉 EntityFramework 将其设置为主键,否则将采用约定。

即,命名为ID 或以ID 为后缀的属性,例如PokemonID 用于 Pokemon 表。 IDId 在这种情况下不区分大小写。

仅当您希望LectureCompletion 类中的外键属性名称与您引用的类不同时,才使用外键属性。例如,如果您的ApplicationUser 类的主键是ApplicationUserId,但在LectureCompletion 类中您希望它是UserId,那么您可以添加属性。

这样做

public class LectureCompletion

    [Key] // Defined only once
    public LectureCompletionId  get;set; 

    // Not needed if Lecture class has the primary key property of LectureId,
    // which is your case.
    [ForeignKey("Lecture")] // Name of your navigation property below.
    public int LectureId  get;set; 

    public Lecture Lecture  get; set; 

    [ForeignKey("ApplicationUser")]
    public int UserId get;set;

    public ApplicationUser ApplicationUser  get; set; 

    public bool Completed  get; set; 

对于 EntityFramework Core,ColumnOrder 目前似乎没有任何效果。

【讨论】:

以上是关于Entity Framework Core “实体类型‘XXX’需要定义一个主键。”的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework Core中更改跟踪工作原理

Entity Framework Core中更改跟踪工作原理

如何将动态实体设置为 dbcontext Entity Framework Core?

什么是自有实体?何时以及为什么在 Entity Framework Core 中使用 Owned Entity?

Entity Framework Core - 如何处理相关实体映射和保存

更新 ASP.NET Core Entity Framework 中的实体类