2012-01-20 28 views
7

ile kod benim sorunun küçük ölçekli temsil etmektedir.kendinden referanslı Varlık Framework

Özelliklerin semantik olarak ayrılmasını ve SQL Server'da tüm alt kategorileri (alt ilişkinin alt öğesi (yinelemeli yukarıdan aşağı)) ve diğerinin tüm üst kategorileri elde etmek için iki farklı ilişki oluşturmasını nasıl söylerim (Ebeveynin ebeveyni (özyineli alttan yukarı))? Böyle bir şey:

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

Ben ModelBuilder ile denedim ama oradan sadece ayrıntı bir seviye elde edebilirsiniz.

+0

Kategori başına birden çok aileniz var mı, yoksa yalnızca bir tane var mı? Ben de tam olarak ne istediğini anlamıyorum. Ağaçtan köküne tüm kategorileri bir şekilde içeren bir koleksiyon 'ebeveynKategorileri' ister misiniz? Evet ise, bu bir navigasyon özelliği olmayacaktır, ancak bir çeşit değerlendirme veya bir geçişin sonucudur. EF size yardım etmeyecek, böyle bir koleksiyon oluşturmak için kendi kodunuzu yazmanız gerekiyor. – Slauma

+0

evet tam olarak. ağacın alt kısmındaki tüm alt kategorileri ve aynı şekilde tüm ana kategorileri ağacın üstüne veren bir şey istiyorum ... ve evet EF'in bu durumda yardımcı olamayacağını anlıyorum, bu yüzden IEnmuerable'nin bazı özyinelemelerini yaptım ve benim için çalışıyor .. Desteğiniz için teşekkürler –

cevap

7

Modellerimdeki bir Çalışan tablosundaki klasik yönetici/çalışan öz-referans ilişkisi olarak tüm çocuk düğümlerini projelerimden birinde n derinliğine getirme sorunu yaşadım. Slauma ve Milracle'nin belirttiği gibi, EF tüm düğümleri belirli bir ebeveynin altında n derinliğine getirmenize yardımcı olmayacaktır. Ancak, bu sorunu depomda bir Breadth-first search algorithm kullanarak çözmeyi başardım. Lütfen dikkat, amacım sadece tüm çocuk düğümlerini almak değil, tekrarlayan LINQ sorgularını kullanmak en üst düzey yönetim için iki dakikadan fazla sürdüğü için. Bu yöntemi kullanarak, şimdi iki saniyeden daha kısa bir sürede yürütülür.

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

Ayrıca bir dipnot olarak, bu Dictionary optimization makaleden yardımıyla sözlükte look-ups verimliliğini artırmak başardı.

+0

Bu çözüm sadece iki düzeyde arama yapmak değil mi? Bir şey mi eksik? –