首页 > 解决方案 > 使用 EF Core 5 的 Direct 和 Indirec 多对多配置

问题描述

我有以下实体

public class Course
{
    public long Id { get; set; }
    public virtual ICollection<User> Users{ get; set; }
    public virtual ICollection<UserCourse> CourseUsers { get; set; }
}

public class User
{
    public long Id { get; set; }
    public virtual ICollection<Course> Courses { get; set; }
    public virtual 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; }

    public bool IsRequired { get; set; }
}

具有以下映射

用户课程映射:

        builder
            .HasOne(nav => nav.User)
            .WithMany(self => self.UserCourses)
            .HasForeignKey(fk => fk.UserId)
            .OnDelete(DeleteBehavior.Cascade);

        builder
            .HasOne(nav => nav.Course)
            .WithMany(self => self.CourseUsers)
            .HasForeignKey(fk => fk.CourseId)
            .OnDelete(DeleteBehavior.Cascade);

和用户映射

        builder
            .HasMany(nav => nav.Courses)
            .WithMany(nav => nav.Users);

当尝试创建一个新的迁移时,我不确定我为什么会得到这个。

不能将表 'UserCourse' 用于实体类型 'UserCourse',因为它正用于实体类型 'UserCourse(Dictionary<string, object>)' 和可能的其他实体类型,但没有链接关系。将外键添加到主键属性上的“UserCourse”,并指向映射到“UserCourse”的另一个实体上的主键。

我了解错误是什么,但不确定如何强制 UserCourse 映射使用用户映射生成的连接表,反之亦然

另外,我需要 OData 的直接映射,以及使用连接实体的间接映射来进行操作DbSet<UserCourse>

标签: c#.netentity-framework-coreef-core-5.0

解决方案


public virtual ICollection<User> Users{ get; set; }inCourse实体和public virtual ICollection<Course> Courses { get; set; }inUsers实体是多余的。实体应该看起来更像这样

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

public class User
{
   public long Id { get; set; }
   public virtual 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; }

}

并且 OnModelCreating 方法应该有这个代码

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);  

    }

如果您使用 EF core 5,您可以直接跳过连接表。它将由 EF 在幕后生成和处理。更多关于这里的主题https://www.thereformedprogrammer.net/updating-many-to-many-relationships-in-ef-core-5-and-above/


推荐阅读