Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework EF6将具有两个外键的子记录添加到父表_Entity Framework_Entity Framework 6 - Fatal编程技术网

Entity framework EF6将具有两个外键的子记录添加到父表

Entity framework EF6将具有两个外键的子记录添加到父表,entity-framework,entity-framework-6,Entity Framework,Entity Framework 6,我的问题涉及一个任务表,以及它们之间的关系 业务模型是,每个任务都有一个在开始之前需要完成的任务列表 我的C#EF6 winforms应用程序有以下两个表(简化) 我有一个主键为的任务表 [TaskID] [int] IDENTITY(1,1) NOT NULL 和只有两列的前置表 [TaskID] [int] NOT NULL, [PredecessorTaskId] [int] NOT NULL 其中主键由两列组成 TaskID和PredecessorTaskId都是任务表的外键 在de

我的问题涉及一个任务表,以及它们之间的关系

业务模型是,每个任务都有一个在开始之前需要完成的任务列表

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

我有一个主键为的任务表

[TaskID] [int] IDENTITY(1,1) NOT NULL
和只有两列的前置表

[TaskID] [int] NOT NULL,
[PredecessorTaskId] [int] NOT NULL
其中主键由两列组成

TaskID
PredecessorTaskId
都是任务表的外键

在designer edmx中,我看不到前置表,而是有一行从任务表返回到它本身

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

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 
}
我明白了

这不是我想要的,因为它是第一个应该具有空数据的前置任务,指示第一个任务不需要任何其他任务来启动

如果在循环中取消对SaveChanges调用的注释,则会得到正确的结果

但是,我更希望只调用一次SaveChanges,因此有一个事务

我还尝试添加

prevtask.NeededByTasks.Add(task);
打电话给

task.NeedsTasks.Add(prevtask);

但是,它没有什么区别

它实际上是SQL结果中包含
NULL
数据的第一个前置元素(即
workflowTasks
列表中的第一个元素)。如果稍微扩展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
(正如您已经看到的)来明确地强制生成密钥,否则我不会以任何方式依赖于以我想要的特定顺序生成密钥的期望

通过使用(var scope=newtransactionscope()){…scope.Complete();}块将整个循环包装到一个
中,可以解决在单个事务中运行多个
SaveChanges
调用的问题

然而,问题是:您真的需要排序的
任务ID
?如果根本不引用键,您实际上可以按照任务的依赖关系顺序运行任务,例如:

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
    }
}
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
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
    }
}