[英]self-referencing with 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; }
}
当我在Entity Framework中使用此类时,它只生成父类和子类的一个关系。
如何在语义上区分属性,并在SQL Server中生成两个不同的关系,用于获取所有子类别(子关系的子项(自顶向下递送)),另一个用于获取所有父类别(父项的父项) (递归自下而上))? 像这样的东西:
public virtual ICollection<Category> childCategories { get; set;}
public virtual ICollection<Category> parentCategories { get; set;}
我尝试使用模型构建器,但从那里我只能得到一个细节级别。
在我的一个项目中,我遇到了将所有子节点检索到n深度的问题,作为模型中Employee表上的经典主管/员工自引用关系。 正如Slauma和Milracle指出的那样,EF不会帮助您在指定父级下检索所有节点到n的深度。 但是,我能够在我的存储库中使用广度优先搜索算法来解决这个问题。 请注意,我的目标不仅是检索所有子节点,而且要快速执行,因为使用递归LINQ查询需要超过两分钟才能完成最高级别的管理。 使用此方法,它现在可在不到两秒的时间内执行。
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();
}
此外,作为一个脚注,我可以借助此词典优化文章提高字典中查找的效率。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.