Entity FrameWork и наследование

269
23 октября 2021, 05:20

Прошу разрешить диллему, суть которой такова:
Есть БД с сущностями представляющими факультет (студент, преподаватель, оценки, кафедры, и т.д.), сделанная с помощью EF CodeFirst. Есть WinForms приложение с кнопочками и прочим. (не суть) Преподаватель поставил задачу: создать разные учетные записи, присвоить им роли и в зависимости от роли - разный функционал. Я решил таким путем : просто 3 разные формы показываются в зависимости от роли: админ - одна форма, студент - другая, преподаватель - третья. Вопрос же в том, как мне связать LoginModel, в которой содержатся Login, Password и сущности студента или преподавателя.

Грубо говоря: вводим данные в форму для входа, просматриваем в БД совпадения и нашли того пользователя User, у него есть Role. Тут разобрались. Но представим, что учетная запись User связана с студентом и он может просматривать свои данные, тогда нам надо User связать с Student один к одному. Но а если это преподаватель? Значит надо связать и с преподавателем один к одному - костыль, т.к. при добавлении других сущностей у нас будут добавляться связи, из которых только одна будет не null.

Answer 1

Попробую привести пример, чтобы было понятно о чем я.

Допустим, у нас есть следующая бизнес логика.

#region Business logic 
public abstract class Person
{
    public string Name { get; set; }
    public abstract void SayHello();
}

public class Student : Person
{
    public override void SayHello()
    {
        Console.WriteLine($"Hello, Im {this.Name} and Im a Student");
    }
}
public class Admin : Person
{
    public override void SayHello()
    {
        Console.WriteLine($"Hello, Im {this.Name} and Im a Admin");
    }
}
public class Professor : Person
{
    public override void SayHello()
    {
        Console.WriteLine($"Hello, Im {this.Name} and Im a Professor");
    }
}
#endregion

Давайте напишем часть слоя для хранения данных для неё.

#region database
public class Repository
{
    public Person GetUser (string name){
        var context = new DatabaseContext();
        var dto = context.Users.FirstOrDefault(x => x.Name == name);
        if (dto.Roles.Contains("Admin")) return new Admin() {Name = dto.Name};
        if (dto.Roles.Contains("Student")) return new Student() {Name = dto.Name};
        if (dto.Roles.Contains("Professor")) return new Professor() {Name = dto.Name};
        return null;
    }
}
public class DatabaseContext 
{
    public List<UserDto> Users { get; set; } = 
        new List<UserDto>() {
            new UserDto() {
                Name = "Vasya",
                Roles = new List<string>(){"Student"}
            },
            new UserDto() {
                Name = "Petya",
                Roles = new List<string>(){"Professor"}
            },
            new UserDto() {
                Name = "Kolya",
                Roles = new List<string>(){"Admin"}
            }
            };
}

public class UserDto{
    public string Name{get;set;}
    public List<string> Roles {get;set;} = new List<string>();
}
#endregion

Как видите, храним мы только юзеров и роли. Нам не надо хранить студентов или ещё что то.

Проверим наше предположение

var repo = new Repository();
var user = repo.GetUser("Vasya");
user.SayHello();

Вывод получится

Hello, Im Vasya and Im a Student

Отмечу также, что во многих случаях отдельные классы бизнес логики для ролей типа Студент или Профессор вообще не нужны, и обычно возможности юзера зависят только от его ролей, потому необходимость отдельных классов остается на вашей совести.

Answer 2

нужна таблица роли (админ, студент, препод, при необходимости можно добавить и другие роли), а у каждого User нужно указать не саму роль, а Id_роли (из таблицы ролей).

можно обойтись одной формой, просто в зависимости от роли отображаются либо не отображаются некоторые элементы формы

READ ALSO
Order by many to many relation in laravel

Order by many to many relation in laravel

Имеем отношение Many to Many

196
Замена хэштегов на ссылки

Замена хэштегов на ссылки

Пытаюсь реализовать хэштегиЗаменить каждый хэштег на ссылку

80
Как замокать метод с обращением в БД

Как замокать метод с обращением в БД

Есть класс с двумя методами, один оперирует данными взятыми из второгоНужно протестировать метод sum не получая данных из метода db, а подставив...

199
Получить все возможные значения из БД

Получить все возможные значения из БД

У меня есть система файлов и папокВ данном контексте - папка и файл некое структурированное значение в БД

197