2011-08-23 72 views
2

我对使用实体框架很陌生,而且我很难弄清楚如何编写使用多对多关系的查询。我有3个实体。 角色,用户安全。 A 角色可以有多个安全和一个安全可以分配给很多角色。 A 角色可以有多个用户用户可以有多个角色如何编写一个涉及多对多关系的EF查询

我的问题是:我该如何着手编写一个查询,该查询为给定的用户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; } 
} 

回答

2

未经检验的,但是从我的头顶,将是这样的:

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

这看起来像个胜利者,明天我会试一试 –

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语句wheras使用INNER JOIN: -

IEnumerable<Securable> securablesForUser = context.Securables.Where(
    x => x.Roles.Any(y => y.Users.Any(z => z.UserId == userId))).Distinct(); 

使用WHERE EXISTS这在我们的基准测试中比比查询两次。

一如既往,如果您有性能问题,我建议进行分析。您的数据结果可能会有所不同。 如果你不太在意配置文件,那么你并不关心优化!

+0

嗯,简单的解决方案,但我相信这一点,如果延迟加载启用才有效?此外,这将需要两个SQL查询,一个获取用户,然后第二个获取安全性? –

+0

如果这是一个性能瓶颈,那么在加载用户时可以急切加载角色和安全策略。除非你显示的是用户列表,否则我可能不会打扰。 –

+0

不,这个查询工作正常,没有延迟加载。它甚至可以在EF 1中工作。急切的加载不会有帮助;它现在很好。 –