2014-01-22 67 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 
    } 
} 
相關問題