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
这会使程序崩溃,因为 UserRoles
是 null
,那么 .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 会知道
我仍在学习 .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
这会使程序崩溃,因为 UserRoles
是 null
,那么 .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 会知道