如何配置多对一关系?

时间:2019-05-14 12:14:43

标签: c# mysql asp.net-core entity-framework-core

目前,我正在使用Mysql数据库在dotnet核心中使用Rest api。目前,我有两个带有用户和角色的表。对于我的项目,我需要获得用户和角色。在我的代码中,我指定了此样本中所述的关系

public DbSet<User> Users { get; set; }
private void InitEntityRole(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Role>(entity =>
    {
         entity.Property(e => e.Id).ValueGeneratedOnAdd().HasColumnName("Id");
         entity.Property(e => e.Name).HasColumnName("naam");
    });
}

private void InitEntityUser(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>(entity =>
    {
        entity.Property(e => e.Id).ValueGeneratedOnAdd().HasColumnName("Id");
        entity.Property(e => e.Username).HasColumnName("gebruikersnaam");
        entity.Property(e => e.PasswordHash).HasColumnName("wachtwoord");
        entity.Property(e => e.PasswordSalt).HasColumnName("salt");
        entity.HasOne(u => u.Person)
            .WithOne(p => p.User)
            .HasForeignKey<Person>(p => p.Id)
            .HasConstraintName("fk_persoon");
        entity.HasOne(u => u.Role)
            .WithMany(r => r.Users)
            .HasForeignKey(r => r.Id)
            .HasConstraintName("fk_gebruikerrol");
      });
}

在我的代码中,我有一个测试功能来检索所有这样的用户

public List<User> GetAll()
{
    var users = _dbContext.Users.Include(u => u.Role).ToList();
    users.ForEach(u => u.Password = null);

    return users;
}

我的模特:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DamstraChallengeBackend.Models
{
    [Table("rol")]
    public class Role
    {
        public int Id { get; set; }
        public string Name { get; set; }

        [JsonIgnore]
        public ICollection<User> Users { get; set; }
    }
}

和:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;    
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DamstraChallengeBackend.Models
{
    [Table("gebruiker")]
    public class User
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public string Username { get; set; }
        [NotMapped]
        public string Password { get; set; }
        [JsonIgnore]
        public byte[] PasswordHash { get; set; }
        [JsonIgnore]
        public byte[] PasswordSalt { get; set; }
        public Person Person { get; set; }
        public Role Role { get; set; }

        [NotMapped]
        [JsonIgnore]
        public string Token { get; set; }

    }
}

我的表配置为

用户:

CREATE TABLE `gebruiker` (
   `Id` int(11) NOT NULL AUTO_INCREMENT,
   `gebruikersnaam` varchar(255) NOT NULL,
   `wachtwoord` blob NOT NULL,
   `salt` blob NOT NULL,
   `p_id` int(11) NOT NULL,
   `r_id` int(11) NOT NULL,
    PRIMARY KEY (`Id`),
    KEY `fk_persoon` (`p_id`),
    KEY `fk_gebruikerrol` (`r_id`),
    CONSTRAINT `fk_gebruikerrol` FOREIGN KEY (`r_id`) REFERENCES `rol` (`Id`),
    CONSTRAINT `fk_persoon` FOREIGN KEY (`p_id`) REFERENCES `persoon` (`Id`)
) 
ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 
COLLATE=utf8mb4_0900_ai_ci

角色:

CREATE TABLE `rol` (
    `Id` int(11) NOT NULL AUTO_INCREMENT,
    `naam` varchar(255) NOT NULL,
     PRIMARY KEY (`Id`)
) 
ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 
COLLATE=utf8mb4_0900_ai_ci

执行此代码时,我得到的只是一个空数组。我认为我在配置方面出错了,但似乎找不到。请任何人能帮助我。

我尝试过的事情是:忽略包含,然后得到一个数组,其中包含没有角色的用户。但是,一旦我添加了include语句,一切都不会显示。

我感到奇怪的是,当我有一个用户与一个组一起使用时,它可以工作。一旦添加更多,我得到的就是一个空数组。

对于英语中的错误我深表歉意,但我希望它足够清楚。

1 个答案:

答案 0 :(得分:1)

编辑:在github上添加了具有in-memory-db-context的有效示例解决方案。

关系是错误的,这可能导致实体框架以这种方式运行。这是实体类型User与实体类型Role之间的多对多关系。一个用户具有0..1n个角色,1个角色已分配给0..n个用户。

所以您需要做的是以下

1:添加同时包含外键和唯一标识符的映射实体类型UserRole

public class UserRole
{
   public int Id { get; set; }
   public int UserId { get; set; }
   public User User { get; set; } 
   public int RoleId { get; set; }
   public Role Role { get; set; }
}

2:调整实体类型的用户

public class User 
{
   // more code probably here
   public virtual ICollection<UserRole> UserRoles { get; set; } // virtual keyword necessary for lazy loading, can be left out if not wanted
}

3:调整实体类型角色

public class Role
{
    public int Id { get; set; }
    public string Name { get; set; }

   public virtual ICollection<UserRole> UserRoles { get; set; } // virtual keyword necessary for lazy loading, can be left out if not wanted
}

4:在OnModelCreating(ModelBuilder builder)内调整DbContext方法,并删除旧的关系映射并添加新的映射。

protected override void OnModelCreating(ModelBuilder builder)
{
   // existing code here
   modelBuilder.Entity<UserRole>()
     .HasOne(ur => ur.User)
     .WithMany(u => u.UserRoles)
     .HasForeignKey(ur => ur.RoleId);

   modelBuilder.Entity<UserRole>()
     .HasOne(ur => ur.Roles)
     .WithMany(r => r.UserRoles)
     .HasForeignKey(ur => ur.UserId);

}

5:创建新模型并更新数据库,您可能必须删除现有模型

6:如果要在用户中包含角色,请执行类似的查询

var usersWithRoles = context.Set<User>().Include(u => u.UserRoles).ThenInclude(ur => ur.Roles);

Sadly it doesn't work yet without the mapping-entity

More samples can be found here