2011-08-23 108 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中工作。急切的加載不會有幫助;它現在很好。 –