我很擅长使用实体框架,但是我无法理解如何编写使用多对多关系的查询。我有3个实体。 角色,用户和安全。 角色可以有多个 Securables ,安全可以分配给多个角色。 角色可以包含多个用户,用户可以包含多个角色。
我的问题是:我如何编写一个查询,为给定的用户ID提供了明确的Securables列表?
这是我的模型,EF会自动为我创建链接表。
public class SecurityContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<Securable> Securables { get; set; }
}
public class User
{
public Guid UserId { get; set; }
public string Forename { get; set; }
public string Surname { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
public class Securable
{
public Guid SecurableId { get; set; }
public string Name { get; set; }
public virtual ICollection<Role> Roles { get;set;}
}
public class Role
{
public Guid RoleId { get; set; }
public string Name { get; set; }
public virtual ICollection<Securable> Securables { get; set; }
public virtual ICollection<User> Users { get; set; }
}
答案 0 :(得分:2)
未经测试,但在我的脑海中,它将是这样的:
var context = new DbContext();
var result = context.Securables
.Where(s => s.Roles
.Any(r => r.Users
.Any(u => u.UserId = userId)))
.Distinct();
答案 1 :(得分:1)
喜欢这个吗?
User user = ...;
IEnumerable<Securable> securablesForUser =
user.Roles.SelectMany(x => x.Securables).Distinct();
<强>更新: - 强>
在一个真正成为性能瓶颈的项目之后,我进行了更深入的调查,发现以下LINQ查询生成了最好的SQL(对于我们的数据): -
IEnumerable<Securable> securablesForUser =
context.Users.Where(x => x.UserId == userId)
.SelectMany(x => x.Roles)
.SelectMany(x => x.Securables)
.Distinct();
这将在翻译的SQL语言中使用INNER JOIN
: -
IEnumerable<Securable> securablesForUser = context.Securables.Where(
x => x.Roles.Any(y => y.Users.Any(z => z.UserId == userId))).Distinct();
使用WHERE EXISTS
在我们的基准测试中慢比查询两次。
与往常一样,如果您有性能问题,我建议进行性能分析。您的数据结果可能有所不同。 如果您不关心配置文件,那么您并不在乎优化!