2012-01-20 17 views
7

kodu reprezentują niewielką skalę mojego problemu:własnym przedstawieniu z Entity Framework

public class Category 
{ 
    public Guid CategoryID { get; set; } 
    public string Name { get; set; } 
    public Guid? ParentID { get; set; } 
    public bool IsTop { get; set; } 
    public string Description { get; set; } 

    public virtual Category parentCategory { get; set; } 
} 

Kiedy użyć tej klasy w Entity Framework, generuje tylko jedną relację ojca i dziecka kategoriach.

Jak odróżnić semantykę właściwości i wygenerować dwie różne relacje w SQL Serverz po to, by uzyskać wszystkie kategorie dzieci z (potomkiem związku dziecka (rekursywna zstępująca)), a drugą dla uzyskania wszystkich kategorii rodzicielskich (rodzic rodzica (rekursywny bottom-up))? Coś takiego:

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

Próbowałem go z modelBuilder, ale stamtąd mogę uzyskać tylko jeden poziom szczegółowości.

+0

Czy masz wielu rodziców w danej kategorii lub tylko jednego? Ja również nie rozumiem, czego dokładnie chcesz. Czy chcesz utworzyć kolekcję 'parentCategories', która zawiera w jakiś sposób wszystkie kategorie w drzewie do katalogu głównego? Jeśli tak, nie byłoby to właściwością nawigacji, ale jest jakąś oceną lub wynikiem przejścia. EF ci nie pomoże, musisz napisać własny kod, aby stworzyć taką kolekcję. – Slauma

+0

tak dokładnie. Chcę czegoś takiego, co daje mi wszystkie kategorie dzieci w dół drzewa i tak samo wszystkie kategorie rodziców do drzewa ... i tak, zdaję sobie sprawę, że EF nie pomoże w tej sytuacji, więc zrobiłem kilka pętli rekurencyjnych IEnmuerable i to działa dla mnie .. dziękuję za wsparcie –

Odpowiedz

7

Miałem problem z pobieraniem wszystkich węzłów podrzędnych do głębokości n w jednym z moich projektów jako klasyczna relacja między opiekunem/pracownikiem na stole pracownika w moim modelu. Jak zauważyli Slauma i Milracle, EF nie pomoże ci odzyskać wszystkich węzłów na głębokość n pod określonym rodzicem. Jednak udało mi się rozwiązać ten problem za pomocą Breadth-first search algorithm w moim repozytorium. Proszę zauważyć, że moim celem było nie tylko pobranie wszystkich węzłów podrzędnych, ale szybkie wykonanie tego, ponieważ używanie rekurencyjnych zapytań LINQ wymagało więcej niż dwóch minut na najwyższe poziomy zarządzania. Dzięki tej metodzie jest teraz wykonywany w mniej niż dwie sekundy.

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(); 
} 

także jako przypis, byłem w stanie zwiększyć wydajność look-up w słowniku z pomocą tej Dictionary optimization artykułu.

+0

Czy to rozwiązanie nie umożliwia wyszukiwania tylko na dwóch poziomach? Czy czegoś brakuje? –