2014-12-31 4 views
2

다음 모델이 있습니다. 각 모듈에는 모듈 유형의 ​​하위 컬렉션이 있습니다. 각 모듈에는 권한 모음이 있습니다.ASP.NET EF6 쿼리 모델

[DataContract(IsReference = true)] 
public class Module 
{ 
    [Key] 
    [DataMember] 
    public Guid ModuleId { get; set; } 

    [Required] 
    [StringLength(100)] 
    [DataMember] 
    public string Title { get; set; } 

    [StringLength(100)] 
    [DataMember] 
    public string Description { get; set; } 

    [StringLength(50)] 
    [DataMember] 
    public string Icon { get; set; } 

    [Required] 
    [RegularExpression(@"[^\s]+")] 
    [StringLength(50)] 
    [DataMember] 
    public string Route { get; set; } 

    [DataMember] 
    public ICollection<Permission> Permissions { get; set; } 

    [DataMember] 
    public Guid? ParentModuleId { get; set; } 

    [ForeignKey("ParentModuleId")] 
    [DataMember] 
    public virtual ICollection<Module> Children { get; set; } 
} 
[DataContract(IsReference = true)] 
public class Permission 
{ 
    [Key] 
    [DataMember] 
    public Guid PermissionId { get; set; } 

    [Required] 
    [StringLength(100)] 
    [DataMember] 
    public string Role { get; set; } 

    [DataMember] 
    public Guid ModuleId { get; set; } 

    [ForeignKey("ModuleId")] 
    [DataMember] 
    public Module Module { get; set; } 
} 

다음과 같이 모두 쿼리 루트 함수를 사용하여 모든 루트와 하위를 올바르게 반환합니다.

public override IQueryable<Module> All() 
    { 
     return this.Context.Set<Module>().Include(c => c.Children).Where(p => p.ParentModuleId == null); 
    } 

이제 권한 "사용자"가있는 하위 항목과 동일한 루트 목록을 반환하고 싶습니다. 어떻게해야합니까? 이것은 내가 지금까지 가지고있는 것이다. 이렇게하는 올바른 방법입니까? 도와주세요.

return this.Context.Set<Module>().Include(c => c.Children).Where(p => p.ParentModuleId == null).Include(p => p.Permissions).Where(s => s.Permissions.Any(r=>r.Role=="User")); 

btw, 나는이 기능을 적절하게 사용하는 방법, include, where, any, 많은 기능을 선택하는 방법을 모릅니다. 이것에 대한 모든 자습서 또는 책은 높이 평가됩니다. 내가 어떤 키워드를 검색할지 모르니까 나는 이것에 대한 좋은 튜토리얼을 찾을 수 없다. 이 EF 또는 LINQ입니까?

+0

코드가 올바른 것처럼 보입니다. 문제가 있습니까? 하지만 루트 모듈의 권한 세트 만 검사하고 자식은 체크하지 않습니다. – Dan

+0

나는 게으른 로딩이 기본적으로 활성화되어 있다고 덧붙이고 싶다. 즉, 게으른 로딩을 특별히 비활성화하지 않는 한'.Include'를 사용할 필요가 없다는 것을 의미한다. 직접 네비게이션 속성에 접근 할 수 있고 EF가 게으른로드 그것. – Dan

+0

문제는 어린이들과 관련이 있습니다. 어린이들에 대한 허가를 확인하지 않고 있습니다. 나는 그것을 어떻게합니까? –

답변

0

Include 메서드는 Entity Framework에서 레코드를 가져 오기 위해 데이터베이스로 이동할 때 특정 탐색 속성을 채우도록 지시합니다. 즉, 느린 로딩을 사용하는 대신 데이터를로드하기 때문에 EF가 나중에 데이터베이스). 그것은 어떤 종류의 필터링도하지 않습니다. 모든 것은 'Where` 방법으로 수행됩니다.

1) 재귀 적으로 모두를 사로 잡고 SQL에서 공통 테이블 표현식을 만듭니다

모든 아이들에 걸쳐 요구하고 필터링의 종류를 수행하는 방법은 두 가지 중 하나를 수행해야합니다 특정 모듈의 하위 항목을 찾아 CTE를 SQL보기에두고 EF 엔티티를 해당보기에 매핑 한 다음 을 포함하여 Permissions 테이블에 해당보기를 쿼리하면 찾고있는 권한을 가진 사용자 만 잡을 수 있습니다.

2) T-SQL을 사용하지 않고이 작업을 수행하려면 [NotMapped] 클래스를 사용하여 모든 자식을 거치고 ' 다시 찾아야합니다 (참고 : 첫 번째 것보다 많은 리소스가 필요하며 LINQ to Entities 대신 LINQ to Objects 쿼리가 주로 사용되므로 응용 프로그램에서 느려질 것입니다). 이 같은

뭔가 :

[NotMapped] 
public List<Module> GrabModulesWithPermission(string permission) 
{ 
    var toReturn = new List<Module>(); 

    if (this.Children != null && this.Children.Any(c => c.Permissions.Any(r => r.Role == permission)) 
    { 
    toReturn.AddRange(this.Children.Where(c => c.Permissions.Any(r => r.Role == permission).SelectMany(c => c.GrabModulesWithPermission(permission))); 
    } 

    toReturn.Add(this); 

    return toReturn; 
} 

지금까지 튜토리얼 가서, 내가보기 엔 인 Pluralsight보고 추천 할 것입니다. Microsoft의 EF MVP 인 Julie Lerman이 포함 된 EF에는 여러 가지 비디오가 있습니다.