2016-03-12 59 views
2

下面是程序的流程:如何還原更改對分離的實體

  1. 取實體列表,並使用它們。這將斷開/分離所有實體與上下文。
  2. 對其中一個實體進行更改並保存。我從上下文加載實體,並將分離實體的更改(標量屬性和關係)應用於新加載的實體。
  3. 我有一個功能,用戶可以恢復在斷開的實體上所做的所有更改。下面是我使用的代碼:

    public async Task RevertChanges() 
    { 
        using (var db = new TwinTailDb()) 
        { 
         //Fansubs.Clear(); 
    
         if (db.Entry(this).State == EntityState.Detached && Id != 0) 
         { 
          db.ArchiveEntries.Attach(this); 
          await db.Entry(this).ReloadAsync(); 
         } 
    
         //await db.Entry(this).Collection(a => a.Fansubs).LoadAsync(); 
        } 
    } 
    

然而,當我附上分離的實體,它拋出此異常:

附加信息:連接類型的實體「TwinTail.Entities .ArchiveEntry'失敗,因爲另一個相同類型的實體已具有相同的主鍵值。如果圖中的任何實體具有衝突的鍵值,則使用「附加」方法或將實體的狀態設置爲「未更改」或「已修改」時可能會發生這種情況。這可能是因爲一些實體是新的並且還沒有收到數據庫生成的關鍵值。在這種情況下,使用'Add'方法或'Added'實體狀態來跟蹤圖形,然後根據情況將非新實體的狀態設置爲'Unchanged'或'Modified'。

注意的方面,因爲我使用的是使用語句是自動處理。

我不知道爲什麼它甚至在主鍵上有衝突,因爲我之前沒有加載其他實體,因爲上一個上下文已經被處理了。

此外,如果我跳過第2步其中我保存實體中的所有更改,它不會引發異常。我留下來想,它仍然被追蹤。

編輯: 以下是我跳過附加時發生的情況,證明該實體是真正分離的。

附加信息:不能爲類型'ArchiveEntry'的實體調用成員'ReloadAsync',因爲該實體不存在於上下文中。要向上下文添加實體,請調用DbSet的Add或Attach方法。

嚴重的是,發生了什麼:(

+0

你配置方面:http://mehdi.me/ambient-dbcontext-in-ef6/

固定結構,重裝後/恢復的實體可以簡單地通過調用完成在第2步? –

+0

那麼,它會自動處理,因爲我使用的是「使用」語法。 – Sylpheed

+0

通過它的PK查詢持久化實體不是最容易的,然後從那個點開始使用它?或者你是否專門嘗試恢復到實體具有的確切值,而不是當前的持久值? – Rytmis

回答

0

回答我自己的問題。

主要問題是我處理上下文的生命週期的方式是錯誤的。此外,附加從另一個上下文加載的實體肯定會引發錯誤。只能在該上下文中使用在上下文中加載的實體。

我的情況太短暫了。我會調整它的生命週期,以便每個事務都有一個上下文(數據庫進程)。

這裏有一個關於如何解決/設計你的架構一個很詳細的文章:

DbContext.Entry(entity).Reload(); 
0

上涉及上下文可能改變狀態附着在實體的一些行動。它可以傳遞一個實體在上下文中的方法時發生。試着將斷點在Entity狀態發生變化時有條件中斷,並確保實體在實際調用attach之前沒有被附加,作爲其他動作的副作用。如果是這種情況,那麼比您試圖附加已經存在的實體附帶,這應該會引起異常。

+0

我也嘗試捕捉異常並檢查其狀態。這是說,即使在例外之後它仍然是分離的。另外,上面發佈的代碼是我在實體上調用的整個函數。我很確定它總是被分離出來,因爲我確信我爲每個操作處理了上下文。 – Sylpheed

+0

您能否給出更多的上下文,瞭解如何實例化包含RevertChanges方法的對象,以及它的生命週期是什麼,以及它是否長期生存並且可能從多個線程調用?是否有可能RevertChanges任務與其他任務並行運行,該任務在** this **實例上運行並與上下文配合使用。 也是_TwinTailDb_直接由EF T4模板生成,還是它包裝DbContext並添加一些邏輯的類? – ironstone13

+0

對不起。是的,TwinTailDb是一個生成的DbContext(繼承)及其模型。我爲每個模型編寫了部分類,以便調用它更容易。 RevertChanges就是其中之一。每個函數都在上下文上執行操作,但在函數結束後立即安全處理。 實體在第一個窗口上實例化,因爲它顯示所有實體。 我所做的唯一工作就是我在問題中列出的3個步驟。我確信這3個並不是在同一時間發生的。在我的應用程序中,用戶只能選擇「保存」或「關閉」(會恢復更改)編輯窗口。 – Sylpheed