C# 如何编写涉及多对多关系的EF查询

C# 如何编写涉及多对多关系的EF查询,c#,.net,entity-framework,entity-framework-4.1,C#,.net,Entity Framework,Entity Framework 4.1,我对使用实体框架非常陌生,我很难理解如何编写使用多对多关系的查询。我有3个实体角色、用户和安全。一个角色可以有多个安全角色,一个安全角色可以分配给多个角色。一个角色可以有多个用户,一个用户可以有多个角色 我的问题是:如何编写一个查询,为给定的用户ID提供一个不同的安全列表? 这是我的模型,EF会自动为我创建链接表 public class SecurityContext : DbContext { public DbSet<User> Users { get; set; }

我对使用实体框架非常陌生,我很难理解如何编写使用多对多关系的查询。我有3个实体角色用户安全。一个角色可以有多个安全角色,一个安全角色可以分配给多个角色。一个角色可以有多个用户,一个用户可以有多个角色

我的问题是:如何编写一个查询,为给定的用户ID提供一个不同的安全列表?

这是我的模型,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; }
}
公共类SecurityContext:DbContext { 公共数据库集用户{get;set;} 公共数据库集角色{get;set;} 公共数据库集安全性{get;set;} } 公共类用户 { 公共Guid用户标识{get;set;} 公共字符串名{get;set;} 公共字符串姓氏{get;set;} 公共字符串用户名{get;set;} 公共字符串密码{get;set;} 公共虚拟ICollection角色{get;set;} } 公务舱保安 { 公共Guid安全ID{get;set;} 公共字符串名称{get;set;} 公共虚拟ICollection角色{get;set;} } 公共阶级角色 { 公共Guid RoleId{get;set;} 公共字符串名称{get;set;} 公共虚拟ICollection安全文件{get;set;} 公共虚拟ICollection用户{get;set;} } 像这样吗

User user = ...;
IEnumerable<Securable> securablesForUser =
  user.Roles.SelectMany(x => x.Securables).Distinct();
使用
WHERE EXISTS
,这在我们的基准测试中比查询两次要


一如既往,如果您有性能问题,我建议您进行评测。结果可能与您的数据不同如果您不太在意个人资料,那么您也不太在意优化未经测试,但在我的脑海中,它会是这样的:

var context = new DbContext();
var result = context.Securables
                    .Where(s => s.Roles
                                 .Any(r => r.Users
                                            .Any(u => u.UserId = userId)))
                    .Distinct();

嗯,这是一个简单的解决方案,但我假设只有在启用了延迟加载的情况下才能工作?此外,这还需要两个sql查询,一个用于获取用户,另一个用于获取安全性?如果这是性能瓶颈,您可以在加载用户时立即加载角色和安全性。除非你正在显示一个用户列表,否则我可能不会麻烦你。不,这个查询在没有延迟加载的情况下运行良好。它甚至可以在EF1中工作。急切的加载不会有帮助;一切正常。这看起来像是个赢家,我明天会测试一下
IEnumerable<Securable> securablesForUser = context.Securables.Where(
    x => x.Roles.Any(y => y.Users.Any(z => z.UserId == userId))).Distinct();
var context = new DbContext();
var result = context.Securables
                    .Where(s => s.Roles
                                 .Any(r => r.Users
                                            .Any(u => u.UserId = userId)))
                    .Distinct();