2012-01-20 3 views
7

와 코드는 내 문제의 작은 규모를 나타냅니다.자체 참조 엔티티 프레임 워크

의미 론적으로 속성을 구분하고 모든 하위 범주 (자식 관계 하위 항목 (재귀 적 하향식))를 가져 오는 SQL Server에서 두 가지 다른 관계를 생성하는 방법과 모든 부모 범주를 가져 오는 방법 (부모 부모 (재귀 상향식))? 이 같은 것 :

public virtual ICollection<Category> childCategories { get; set;} 
public virtual ICollection<Category> parentCategories { get; set;} 

나는 modelBuilder로 시도했지만 거기에서 한 단계의 세부 사항 만 얻을 수 있습니다.

+0

카테고리마다 여러 개의 학부모가 있습니까? 나는 또한 네가 정확히 원하는 것을 이해하지 못한다. 트리에 루트 아래에있는 모든 카테고리를 포함하는 콜렉션'parentCategories'를 원합니까? 그렇다면 네비게이션 속성이 아니며 어떤 종류의 평가 또는 트래버스 결과입니다. EF는 도움이되지 않을 것입니다. 그러한 컬렉션을 만들기 위해 자신 만의 코드를 작성해야합니다. – Slauma

+0

예. 나는 tree와 같은 방법으로 모든 하위 카테고리를 나무 아래까지 제공하는 그런 식으로하고 싶다 ... 그리고 yes 나는이 상황에서 EF가 도움이되지 않을 것임을 알고 있으므로 IEnmuerable의 반복적 인 루프를 만들었다. 그것은 나를 위해 작동합니다 ... 당신의 지원에 감사합니다 –

답변

7

내 모델의 Employee 테이블에서 고전적인 감독자/직원 자체 참조 관계로 내 노드 중 하나에 깊이가있는 모든 하위 노드를 가져 오는 문제가있었습니다. Slauma와 Milira가 지적했듯이 EF는 지정된 부모 아래에서 모든 노드를 깊이 n까지 검색하는 데 도움이되지 않습니다. 그러나, 내 저장소에 Breadth-first search algorithm을 사용하여이 문제를 해결할 수있었습니다. 저의 목표는 모든 자식 노드를 검색하는 것이 아니라 재빨리 LINQ 쿼리를 사용하는 것이 관리 최상위 레벨에 2 분 이상 걸리므로 그렇게 빨리 수행해야한다는 것입니다. 이 방법을 사용하면 2 초 이내에 실행됩니다.

public IEnumerable<string> GetAllSubordinateEmployeeIdsByUserId(string userId) 
{ 
    // Retrieve only the fields that create the self-referencing relationship from all nodes 
    var employees = (from e in GetAllEmployees() 
        select new { e.Id, e.SupervisorId }); 
    // Dictionary with optimal size for searching 
    Dictionary<string, string> dicEmployees = new Dictionary<string, string>(employees.Count() * 4); 
    // This queue holds any subordinate employees we find so that we may eventually identify their subordinates as well 
    Queue<string> subordinates = new Queue<string>(); 
    // This list holds the child nodes we're searching for 
    List<string> subordinateIds = new List<string>(); 

    // Load the dictionary with all nodes 
    foreach (var e in employees) 
    { 
     dicEmployees.Add(e.Id, e.SupervisorId); 
    } 

    // Get the key (employee's ID) for each value (employee's supervisor's ID) that matches the value we passed in 
    var directReports = (from d in dicEmployees 
         where d.Value == userId 
         select d.Key); 

    // Add the child nodes to the queue 
    foreach (var d in directReports) 
    { 
     subordinates.Enqueue(d); 
    } 

    // While the queue has a node in it... 
    while (subordinates.Count > 0) 
    { 
     // Retrieve the children of the next node in the queue 
     var node = subordinates.Dequeue(); 
     var childNodes = (from e in dicEmployees 
          where e.Value == node 
          select e.Key); 
     if (childNodes.Count() != 0) 
     { 
      // Add the child nodes to the queue 
      foreach (var c in childNodes) 
      { 
       subordinates.Enqueue(c); 
      } 
     } 
     // Add the node from the queue to the list of child nodes 
     subordinateIds.Add(node); 
    } 

    return subordinateIds.AsEnumerable(); 
} 

또한, 각주로,이 Dictionary optimization 기사에서 도움을 사전에 살펴 업의 효율성을 높일 수 있었다.

+0

이 솔루션은 단 두 수준에서 검색을하지 않습니까? 내가 놓친 게 있니? –