EF Core Много-много-много скрыть опору - PullRequest
0 голосов
/ 20 ноября 2018

Я все еще изучаю .NET Core 2.1.Я работаю над веб-API, где я использую EF Core.В настоящее время я работаю над отношениями между многими пользователями и ролями.Я хотел скрыть пивот, но я думаю, что он оказался немного хакерским, поэтому я хотел посмотреть, что я могу сделать, чтобы улучшить его.

Я начал с чего-то вроде этого:

public class User
{
    public int Id { get; set; }
    public string UserName { get; set; }

    public virtual ICollection<UserRole> UserRoles { get; set; }
}

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

    public virtual ICollection<UserRole> UserRoles { get; set; }
}

public class UserRole
{
    public int UserId { get; set; }
    public int RoleId { get; set; }
}

Это прекрасно работает, затем я хотел добавить IEnumerable<Role> для пользователя, чтобы упростить доступ и сделать вывод JSON более красивым.В Интернете я нашел статью, в которой это было так:

public class User
{
    // All of the previous code
    [NotMapped]
    public virtual IEnumerable<Role> Roles => UserRoles.Select(x => x.Role);
}

Затем я могу получить пользователей и роли:

_context.Users.Include(x => x.UserRoles).ThenInclude(y => y.Role)

Дело в том, что иногда я хочу получить только пользователейбез ролей:

_context.Users

Это приводит к аварийному завершению программы, поскольку UserRoles равно null, тогда .Select(x => x.Role) завершится ошибкой.

Мое исправление для класса User былоследующее:

public class User
{
    public virtual IEnumerable<Role> Roles
    {
        get
        {
            if (UserRoles == null) return null;
            return UserRoles.Select(x => x.Role);
        }
    }
}

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

public virtual IEnumerable<Role> Roles => UserRoles.Select(x => x?.Role);

Я хочу иметь что-то такое же простое, как в приведенной выше строке, но на самом деле оно должно работать так, как задумано.

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Я всегда инициализирую любую коллекцию в пустом конструкторе (для EF) и всегда вызываю ее из любого другого.В качестве примера:

 public class User
    {
        public int Id { get; set; }
        public string UserName { get; set; }

        public virtual ICollection<UserRole> UserRoles { get; set; }

        public IEnumerable<Role> Roles => UserRoles.Select(x => x.Role);

        public User()
        {
            this.UserRoles = new List<UserRole>();
        }

        public User(string name)
            :this()
        {

        }
    }

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

Также вы не используете [NotMapped]атрибут, поскольку свойство доступно только для чтения, и EF будет знать, что

0 голосов
/ 20 ноября 2018

Попробуйте это:

public virtual IEnumerable<Role> Roles => UserRoles?.Select(x => x.Role);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...