You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core 2.2.6多对多关联添加时触发主键重复错误求助

EF Core多对多关联添加时报主键重复错误的解决方法

项目环境

  • EF Core 2.2.6
  • 通过中间表间接实现多对多关联
  • 数据库中已存在Course记录

错误信息

尝试向中间表添加记录时,抛出以下异常:

MySql.Data.MySqlClient.MySqlException (0x80004005): Duplicate entry '3945' for key 'PRIMARY'

实体类与中间表代码

public class Course
{
    public long Id { get; set; }
    // 填充了引用对象及其ID
    public ICollection<UserCourse> CourseUsers { get; set; }
}

public class User
{
    public long Id { get; set; }
    public ICollection<UserCourse> UserCourses { get; set; }
}

public class UserCourse
{
    public long UserId { get; set; }
    public User User { get; set; }

    public long CourseId { get; set; }
    public Course Course { get; set; }
}

Fluent API配置代码

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<UserCourse>()
        .HasKey(uc => new { uc.UserId, uc.CourseId });

    modelBuilder.Entity<UserCourse>()
        .HasOne(uc => uc.Course)
        .WithMany(c => c.Users)
        .HasForeignKey(uc => uc.CourseId);

    modelBuilder.Entity<UserCourse>()
        .HasOne(uc => uc.User)
        .WithMany(c => c.Courses)
        .HasForeignKey(uc => uc.UserId);
}

问题场景

ID为3945的Course记录已存在于数据库中,但添加关联时EF仍尝试向Course表插入这条记录,导致主键重复错误,需求是仅在中间表创建关联,不修改Course表。


解决方案

核心原因

EF Core将传入的Course实例标记为新增状态,而非已存在的跟踪状态,因此保存时会尝试插入重复ID的记录。

具体解决方法

方法一:直接使用ID创建关联(推荐)

无需实例化Course对象,直接指定UserCourse的CourseId为已存在的ID即可,避免EF误判实体状态:

var userCourse = new UserCourse
{
    UserId = 你的用户ID, // 或传入已跟踪的User实例的Id
    CourseId = 3945 // 直接用已存在的课程ID
};

dbContext.UserCourses.Add(userCourse);
dbContext.SaveChanges();

方法二:附加Course实体到上下文

如果必须使用Course实体对象,需将其附加到上下文,标记为已存在状态:

var existingCourse = new Course { Id = 3945 };
dbContext.Attach(existingCourse); // 附加后EF将其视为已存在的Unchanged状态

var userCourse = new UserCourse
{
    User = 已跟踪的User实例, // 或设置UserId
    Course = existingCourse
};

dbContext.UserCourses.Add(userCourse);
dbContext.SaveChanges();

方法三:修正Fluent API配置的导航属性名

你的配置中存在导航属性名称不匹配的问题:Course类的导航属性是CourseUsers,但配置里写的是.WithMany(c => c.Users);User类的导航属性是UserCourses,配置里写的是.WithMany(c => c.Courses)。这个错误会导致EF无法正确识别关联关系,间接引发状态跟踪问题,必须修正:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<UserCourse>()
        .HasKey(uc => new { uc.UserId, uc.CourseId });

    modelBuilder.Entity<UserCourse>()
        .HasOne(uc => uc.Course)
        .WithMany(c => c.CourseUsers) // 改为Course类实际的导航属性名
        .HasForeignKey(uc => uc.CourseId);

    modelBuilder.Entity<UserCourse>()
        .HasOne(uc => uc.User)
        .WithMany(u => u.UserCourses) // 改为User类实际的导航属性名
        .HasForeignKey(uc => uc.UserId);
}

内容的提问来源于stack exchange,提问作者Tauwin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 08:10:29