2011-08-23 3 views
2

엔티티 프레임 워크를 사용하는 데있어 새로운 경험이 있습니다. 다 대다 관계를 사용하는 쿼리를 작성하는 방법을 고민하는 데 어려움을 겪고 있습니다. 3 개의 엔티티가 있습니다. 역할, 사용자보안 성. 역할 여러 보안 개체에게을 가질 수 있으며, 보안 개체 많은 역할에 할당 할 수 있습니다. A 역할은 복수 사용자사용자은 복수 역할을 가질 수 있습니다..many to many 관계를 포함하는 EF 쿼리를 작성하는 방법

내 질문 : 주어진 사용자 ID에 대한 Securable의 고유 목록을 제공하는 쿼리를 작성하려면 어떻게해야합니까?

여기 내 모델이 있는데, 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를 사용합니다 : -

WHERE EXISTS을 사용합니다.이 벤치 마크에서 은 두 번 쿼리하는 것보다 느림입니다.

항상 성능 문제가있는 경우 프로파일 링을 권장합니다. 데이터 결과가 다를 수 있습니다. 프로필 작성에 신경 쓰지 않으면 최적화 할 필요가 없습니다.

+0

흠, 간단한 솔루션,하지만 난 게으른 로딩이 활성화되어있을 경우에만 동작합니다 같은데요? 또한 이것은 두 개의 SQL 쿼리를 필요로합니다. 하나는 사용자를 얻고, 두 번째는 보안 개체를 얻기 위해서입니다. –

+0

성능 병목 현상이 발생하면 사용자를로드 할 때 역할 및 보안 개체를 열망 할 수 있습니다. 하지만 사용자 목록을 표시하지 않는다면 걱정하지 않아도됩니다. –

+0

아니요,이 쿼리는 지연로드없이 올바르게 작동합니다. 그것은 EF 1에서도 작동 할 것입니다. 열렬한 로딩은 도움이되지 않습니다. 그것은 괜찮습니다. –

관련 문제