Как настроить отношение «многие к одному»? - PullRequest
1 голос
/ 14 мая 2019

В настоящее время я работаю над API отдыха в ядре dotnet с базой данных Mysql.На данный момент у меня есть две таблицы с пользователями и ролями.Для моего проекта мне нужно получить пользователя и роль.В моем коде я уточнил отношения, как указано в этом примере

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

Когда я выполняю этот код, все, что я получаю, это пустой массив.Я думаю, что я сделал ошибку в конфигурации, но я не могу ее найти.Пожалуйста, кто-нибудь может мне помочь.

То, что я попробовал, таково: оставив включение, а затем я получу массив с пользователями без этих ролей.Но как только я добавляю оператор включения, ничего не появляется.

Мне кажется любопытным то, что он работал, когда у меня был один пользователь в группе.Как только я добавляю больше, я получаю пустой массив.

Я прошу прощения за ошибки в моем английском, но я надеюсь, что это достаточно ясно.

1 Ответ

1 голос
/ 14 мая 2019

Редактировать: Добавлен рабочий пример решения с in-memory-db-context на github .

Отношения неверны, что, вероятно, вызывает сущность-каркасвести себя таким образом.Это отношение «многие ко многим» между типом сущности User и типом сущности Role.Один пользователь имеет роли от 0..1 до n, роль 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);

К сожалению, этопока не работает без объекта отображения

Больше образцов можно найти здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...