c# - 使用 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>
解决方案
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/
推荐阅读
- android - 协调器布局未在预览中显示
- wordpress - 如何在 WooCommerce 欧盟增值税中排除国家/地区
- c# - 在 DataTemplate 和 ItemsControl 中从 ContextMenu 绑定 CommandParameter
- authentication - WhatsApp - WhatsApp 服务器如何停止/检测来自未经授权的应用程序的请求?
- api - Keras 功能 API 输入形状错误
- webpack - webpack,忽略特定入口点的大小警告限制
- python - 熊猫合并而不重复列
- google-apps-script - 如何将已编辑的单元格数据复制到新的电子表格,根据已编辑的单元格复制到单元格和工作表中?
- android - 未经外部存储许可的相机意图,照片公开
- mysql - 加载 MySQLdb 模块时出错。你安装了mysqlclient吗?在 MacOS 上