實體框架 - 生命週期



生命週期

上下文的生命週期從例項建立開始,到例項被處置或垃圾回收結束。

  • 在使用ORM時,上下文生命週期是一個非常關鍵的決策。

  • 上下文就像一個實體快取,這意味著它儲存對所有已載入實體的引用,這可能會導致記憶體消耗迅速增加,並可能造成記憶體洩漏。

  • 在下圖中,您可以看到從應用程式到資料庫透過上下文的資料工作流程的上一級,反之亦然。

Data Workflow

實體生命週期

實體生命週期描述了建立、新增、修改、刪除等實體的過程。實體在其生命週期中具有許多狀態。在檢視如何檢索實體狀態之前,讓我們先看看什麼是實體狀態。狀態是型別為System.Data.EntityState的列舉,它宣告以下值:

  • 已新增:實體被標記為已新增。

  • 已刪除:實體被標記為已刪除。

  • 已修改:實體已被修改。

  • 未更改:實體未被修改。

  • 已分離:實體未被跟蹤。

實體生命週期中的狀態更改

有時實體的狀態由上下文自動設定,但也可以由開發人員手動修改。儘管所有從一種狀態切換到另一種狀態的組合都是可能的,但其中一些是沒有意義的。例如,將已新增實體更改為已刪除狀態,反之亦然。

讓我們討論不同的狀態。

未更改狀態

  • 當實體未更改時,它繫結到上下文,但它沒有被修改。

  • 預設情況下,從資料庫檢索到的實體處於此狀態。

  • 當實體附加到上下文(使用Attach方法)時,它也處於未更改狀態。

  • 上下文無法跟蹤它未引用的物件的更改,因此當它們被附加時,它假定它們未更改。

已分離狀態

  • 已分離是新建立實體的預設狀態,因為上下文無法跟蹤程式碼中任何物件的建立。

  • 即使您在上下文的using塊內例項化實體,情況也是如此。

  • 即使在停用跟蹤時從資料庫檢索到的實體也處於已分離狀態。

  • 當實體已分離時,它不會繫結到上下文,因此其狀態不會被跟蹤。

  • 它可以被處置、修改、與其他類結合使用,或以您可能需要的任何其他方式使用。

  • 由於沒有上下文跟蹤它,因此對實體框架沒有意義。

已新增狀態

  • 當實體處於已新增狀態時,您有幾個選項。實際上,您只能將其從上下文中分離。

  • 當然,即使您修改了一些屬性,狀態仍然是已新增,因為將其移動到已修改、未更改或已刪除狀態是沒有意義的。

  • 這是一個新的實體,並且與資料庫中的行沒有對應關係。

  • 這是處於這些狀態之一的基本先決條件(但此規則不受上下文強制執行)。

Added State

已修改狀態

  • 當實體被修改時,這意味著它處於未更改狀態,然後更改了一些屬性。

  • 實體進入已修改狀態後,它可以移動到已分離或已刪除狀態,但即使您手動恢復原始值,它也不能回滾到未更改狀態。

  • 它甚至不能更改為已新增,除非您分離並將實體新增到上下文,因為資料庫中已經存在具有此ID的行,並且在持久化它時會收到執行時異常。

已刪除狀態

  • 實體進入已刪除狀態是因為它未更改或已修改,然後使用了DeleteObject方法。

  • 這是最嚴格的狀態,因為從這種狀態更改為除已分離之外的任何其他值都沒有意義。

如果您希望在塊結束時處置上下文控制的所有資源,請使用using語句。當您使用using語句時,編譯器會自動建立一個try/finally塊並在finally塊中呼叫dispose。

using (var context = new UniContext()) {

   var student = new Student {
      LastName = "Khan", 
      FirstMidName = "Ali", 
      EnrollmentDate = DateTime.Parse("2005-09-01")
   };

   context.Students.Add(student);
   context.SaveChanges();
}

使用長期執行的上下文時,請考慮以下幾點:

  • 隨著您將更多物件及其引用載入到記憶體中,上下文的記憶體消耗可能會迅速增加。這可能會導致效能問題。

  • 當不再需要上下文時,請記住將其處置。

  • 如果異常導致上下文處於不可恢復的狀態,則整個應用程式可能會終止。

  • 隨著資料查詢和更新之間的時間間隔的增長,遇到與併發相關的問題的可能性會增加。

  • 在使用Web應用程式時,請為每個請求使用一個上下文例項。

  • 在使用Windows Presentation Foundation (WPF)或Windows Forms時,請為每個窗體使用一個上下文例項。這允許您使用上下文提供的更改跟蹤功能。

經驗法則

Web應用程式

  • 現在,對於Web應用程式,每請求使用一個上下文是一種常見的最佳實踐。

  • 在Web應用程式中,我們處理的請求非常短,但包含所有伺服器事務,因此這是上下文生存的適當持續時間。

桌面應用程式

  • 對於桌面應用程式(如Win Forms/WPF等),上下文用於每個窗體/對話方塊/頁面。

  • 由於我們不希望將上下文作為應用程式的單例,因此當我們從一個窗體移動到另一個窗體時,我們將將其處置。

  • 透過這種方式,我們將獲得上下文的大部分功能,並且不會受到長期執行上下文的負面影響。

廣告