我正在寻找使用Entity Framework 6构建一个类似“Microsoft Project”的数据层次结构。基本上我需要的是一个可以跟踪任务的不同细节级别的数据结构。所以我希望构建一个支持类似下面的结构,其中一个Task可以有子任务,子任务可以有子任务等等,但它并不总是也不总是相同的深度。
Task
-Task
--Task
--Task
--Task
---Task
---Task
--Task
这里的一些其他帖子提到实体框架中的树层次结构非常困难,但是我无法找到任何信息来表明自EF4以来它是否有所改进,现在不那么困难了。 / em>的
我有一个如下的任务模型,但是当我尝试生成数据库时,它没有按预期生成:
public class Task
{
public int ID { get; set; }
public string Name { get; set; }
public virtual Task Parent { get; set; }
public virtual ICollection<Task> Children { get; set; }
public virtual ICollection<Task> Predecessors { get; set; }
public virtual ICollection<Task> Successors { get; set; }
}
我期待一个数据库,我有一个Tasks表以及Children,Predecessors和Successors表,但我最终得到的只是一个Tasks表,其属性如下:
ID = c.Int(nullable: false, identity: true),
Name = c.String(),
Task_ID = c.Int(),
Parent_ID = c.Int(),
Task_ID1 = c.Int(),
Task_ID2 = c.Int(),
此外,我希望能够将多个不同的数据与这些任务中的每一个相关联。所以,让我们说我的任务是“构建一个表”,我正在跟踪PersonA与PersonB建立它需要多长时间。将该数据与该任务相关联的最佳方法是什么?我应该使用如下的TaskData对象:
public class TaskData
{
public int ID { get; set; }
public int CompletionTime { get; set; }
public virtual Task Task { get; set; }
public virtual Person Person { get; set; }
}
为了使事情更加复杂,我还需要在多个不同的任务中重复使用相同的Task对象。例如“构建游乐场A”可能具有大小为1的子任务“构建表”,而“构建游乐场B”可能具有大小为2的子构建“构建表”但我只希望“构建表”任务在数据库中存在一次然后通过TaskData对象关联数据。
非常感谢提示或帮助确定如何解决上述任何问题。
答案 0 :(得分:2)
一旦你掌握了它,你的层次结构表就不是一个概念太难了。我通常工作数据库优先,而不是代码优先,所以我无法帮助你解决类定义以及其他问题,但理论如下......
您的任务应该具有以下列:
然后,您应该定义一个关系,其中表引用自身,主键侧为Id,外键侧为ParentId。
你不应该拥有的是单独的表格。所有任务都将包含在一个表中。
然后,您的TaskData应定义自己的Id,以及您需要的任何其他内容。如果您希望TaskData可以跨多个Tasks重用,那么创建一个包含TaskDataId和TaskId列的多对多表,使用它们创建一个复合键,并通过该表链接Tasks和TaskData。任何特定于Tasks和TaskData之间的每个关系的数据都可以在Link表中定义。
您必须小心使用层次结构时,请求大量数据时查询的速度会变慢。每次循环时,EF都会生成一个单独的查询。我强烈建议您检索实现存储过程的完整层次结构,该存储过程使用公用表表达式(CTE)并在EF中映射存储过程。
编辑 - 帮助处理任务类(请原谅我,如果不完全正确,但它应该指向正确的方向)。
1 - 创建任务
public class Task
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TaskId { get; private set; }
public string Name { get; set; }
public int? ParentTaskId { get; private set; }
[ForeignKey("ParentTaskId")]
public Task ParentTask { get; set; }
public List<Task> SubTasks { get; set; }
public Task()
{
SubTasks = new List<Task>();
}
}
2 - 将DbSet自动属性添加到DbContext子类
3 - 覆盖DbContext类中的OnModelCreated方法以配置关联。
public class YourContext : DbContext
{
public DbSet<Task> Tasks { get; set; }
// Other stuff
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Task>()
.HasMany(t => t.SubTasks)
.WithOptional(t => t.ParentTask);
}
}