如何解决 Entity Framework 中数据库多对多映射的 Code First?

How to solve Code First from database many-to-many mapping in Entity Framework?

下面显示我的场景的代码片段:

[Table("User")]
public partial class UserModel
{
 public UserModel()
 {
    UserRole = new HashSet<UserRoleModel>();
 }

  public int UserID { get; set; }
  public string FullName { get; set; }
  public virtual ICollection<UserRoleModel> UserRole { get; set; }
}

[Table("UserRole")]
public partial class UserRoleModel
{
    public UserRoleModel()
    {
            User = new HashSet<UserModel>();
    }

   public int RoleID { get; set; }
   public string RoleName { get; set; }
   public virtual ICollection<UserModel> User { get; set; }

}

现在 OnModelCreating(DbModelBuilder modelBuilder) EF 生成如下代码

modelBuilder.Entity<UserModel>()
                .HasMany(e => e.UserRole)
                .WithMany(e => e.User)
                .Map(m => m.ToTable("UserRoleMapping").MapLeftKey("UserID").MapRightKey("UserRoleID"));

现在可以了添加/插入数据到UserRoleMappingtable。但是如何

Get / Update data from UserRoleMapping table ?

我尝试在 create-code-first-many-to-many 之后解决这个问题 post 并提出第三个 class 和 join entity

 public partial class UserRoleMappingModel
    {
        [Key, Column(Order = 0)]
        public Guid UserId { get; set; }
        public UserModel User { get; set; }

        [Key, Column(Order = 1)]
        public int RoleId { get; set; }
        public UserRoleModel UserRole { get; set; }
    }

然后在 UserModelUserRoleModel 中添加 public virtual ICollection<UserRoleMappingModel> UserRoleMapping { get; set; } class

但是当我尝试使用下面的代码从数据库中获取值时

var results = _userRepository.GetAll()
                 .Include(r => r.UserRoleMapping
                 .Select(s => s.UserRole))
                 .SingleOrDefault(e => e.ID == id); 

它抛出 错误

"An error occurred while executing the command definition. See the inner exception for details.System.Data.SqlClient.SqlException (0x80131904): Invalid object name 'dbo.UserRoleMappingModel'.\r\n

即使我在 OnModelCreating 中尝试了以下配置,但没有任何效果如预期的那样

modelBuilder.Entity<UserRoleMappingModel>()
 .HasKey(e => new { e.UserId, e.RoleId });

您的 class UserRoleMappingModel 没有 Table-属性。因此,EF 搜索 Table UserRoleMappingModel 而不是 von UserRoleMapping.

您必须选择:要么映射 n 对 n 关系并且不访问映射-table,要么加载 table 以访问其中的值。

作为解决方法,您可以实施未映射列:

[Table("User")]
public partial class UserModel
{
    public UserModel()
    {
        UserRole = new HashSet<UserRoleModel>();
    }
    public int UserID { get; set; }
    public string FullName { get; set; }
    public virtual ICollection<UserRoleMappingModel> Mappings { get; set; }
    public virtual ICollection<UserRoleModel> UserRole
    {
        get
        {
            return this.Mappings.Select(s => s.UserRole);
        }
    }
}

根据 GertArnold 的回复,我用下面的方式解决了这个问题。

1st 删除以下设置

modelBuilder.Entity<UserModel>()
                .HasMany(e => e.UserRole)
                .WithMany(e => e.User)
                .Map(m => m.ToTable("UserRoleMapping").MapLeftKey("UserID").MapRightKey("UserRoleID"));

第二次添加波纹管设置

modelBuilder.Entity<UserRoleMappingModel>()
 .HasKey(e => new { e.UserId, e.RoleId });

第三次在映射模型中添加table属性

[Table("UserRoleMapping")]
public partial class UserRoleMappingModel
    {
        [Key, Column(Order = 0)]
        public Guid UserId { get; set; }
        public UserModel User { get; set; }

        [Key, Column(Order = 1)]
        public int RoleId { get; set; }
        public UserRoleModel UserRole { get; set; }
    }

第 4 次创建映射存储库

IUserRoleMappingRepository

第5个简单的get方法(问题已解决)

var results = _userRoleMappingRepository.SearchFor(e => e.UserId == id)
                                                            .Select(s => new
                                                            {
                                                                s.UserId,
                                                                s.UserRoleId,
                                                                s.UserRole.RoleName
                                                            })
                                                           .FirstOrDefault();

注意点: 使用波纹管查询我能够得到结果但由于自引用问题

无法使用 Newtonsoft.Json 序列化
var results = _userRepository.GetAll()
                 .Include(r => r.UserRoleMapping
                 .Select(s => s.UserRole))
                 .SingleOrDefault(e => e.ID == id); 

尝试以下 JsonSerializerSettingssetting 或者但无法成功序列化

PreserveReferencesHandling = PreserveReferencesHandling.All / Object
ReferenceLoopHandling = ReferenceLoopHandling.Serialize / Ignore