EF Core 多对多隐藏枢轴

EF Core Many-to-Many hide pivot

我仍在学习 .NET Core 2.1。我在使用 EF Core 的 Web API 上工作。目前我正在研究用户和角色之间的多对多关系。我想隐藏枢轴,但我认为它最终有点老套,所以我想看看我能做些什么来改进它。

我从这样的事情开始:

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

这会使程序崩溃,因为 UserRolesnull,那么 .Select(x => x.Role) 将失败。

我对 User class 的修复如下:

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);

我想要像上面一行一样简单的东西,但它实际上应该按预期工作。

试试这个:

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

我总是在空构造函数(对于 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 会知道