2014-01-22 30 views
1

我的问题涉及一个任务表及其关系。EF6将具有两个外键的子记录添加到父表

业务模型是每个任务都有一个需要完成的任务列表,才能启动。

我的C#EF6 winforms应用程序具有以下2个表(简化的)

我与主键

[TaskID] [int] IDENTITY(1,1) NOT NULL 

任务表和前任表仅具有两列

[TaskID] [int] NOT NULL, 
[PredecessorTaskId] [int] NOT NULL 

其中主键由两列组成。

TaskIDPredecessorTaskId都是任务表的外键。

在设计器edmx中,我看不到前驱表,而是有一行从Task表运行回自己。

通过运行自定义工具创建的代码是

public partial class task 
{ 
    public task() 
    { 
     this.NeedsTasks = new HashSet<task>(); 
     this.NeededByTasks = new HashSet<task>(); 
    } 
    public int TaskID { get; set; } 

    public virtual ICollection<task> NeedsTasks { get; set; } 
    public virtual ICollection<task> NeededByTasks { get; set; } 
    // other fields 
} 

我无法找到的前驱表生成现在

我的代码

​​

如果我运行上面的任何代码代码和查询记录使用

select k.taskid, p.taskid, p.predecessortaskId 
from task k left outer join predecessor p on k.taskid = p.taskid 
where etc 

我得到

taskid taskid predecessortaskid 
568187 568187 568188 
568188 NULL NULL 
568189 568189 568187 
568190 568190 568189 
568191 568191 568190 

这不是我想要的,因为这是应有的空数据,表明第一个任务不需要任何其他任务开始的第一前身。

如果我取消呼叫转移到循环中调用SaveChanges,我得到正确的结果

不过,我更希望有只有一个调用的SaveChanges,所以有一个事务。

我也尝试添加

prevtask.NeededByTasks.Add(task); 

,来电后

task.NeedsTasks.Add(prevtask); 

但它并没有区别

回答

1

实际上是第一个前身(即第一元素在你的workflowTasks列表中)有您的SQL结果中有210个数据。你可以看到它,如果你稍微延长你的SQL查询:

select k.taskid, p.taskid, p.predecessortaskId, k.taskoffsetid 
from task k left outer join predecessor p on k.taskid = p.taskid 
where etc 
order by taskoffsetid 

结果是现在:

taskid taskid predecessortaskid taskoffsetid 
568188 NULL NULL    1 
568187 568187 568188    2 
568189 568189 568187    3 
568190 568190 568189    4 
568191 568191 568190    5 

然而,taskid并没有以同样的顺序生成因为你已经设置的taskoffsetid,并且任务在您的输入列表中排序。

如果插入具有许多实体的复杂对象图,则无法假定生成密钥的任何特定顺序。 EF发送到数据库的INSERT语句的顺序在EF控制下。除非我通过多次调用SaveChanges(正如您已经看到的)明确强制生成密钥,否则我不会以任何方式依赖期望按照特定顺序生成密钥。

通过将整个循环包装到using (var scope = new TransactionScope()) { ... scope.Complete(); }块中,可以解决此问题,以便在单个事务中运行多个SaveChanges调用。

但是,问题是:你真的需要排序taskid?如果没有提及密钥,您可以按其依赖关系的顺序实际运行任务,例如如下所示:

using (var db = new MyDbContext) 
{ 
    var task = db.Tasks.Where(t => !t.NeedsTasks.Any()).SingleOrDefault(); 
    while (task != null) 
    { 
     // run task/do something with task... 
     task = task.NeededByTasks.SingleOrDefault(); // lazy loading 
    } 
} 
相关问题