使用自我追蹤實體
在 Entity Framework 應用程式中,物件內容會負責追蹤物件圖形中實體的變更。不過,在 N-Tier 案例中,物件內容可能無法在修改實體的層上使用。從 .NET Framework 4 版開始,自我追蹤實體可協助您追蹤任何層中的變更。
注意: |
---|
如果物件圖形在某層發生變更,而物件內容無法在該層使用時,才應該使用自我追蹤實體。如果物件內容可用,請使用 EntityObject 衍生型別、「單純」的 CLR 物件 (POCO) 型別或 POCO Proxy 型別。如需詳細資訊,請參閱使用物件。 |
從 Microsoft Visual Studio 2010 開始,[ADO.NET 自我追蹤實體產生器] 範本就會產生自我追蹤實體。這個範本項目會產生兩個 .tt (文字範本) 檔案:<模型名稱>.tt 和 <模型名稱>.Context.tt。<模型名稱>.tt 檔案會產生實體類型和 Helper 類別,而這個類別包含自我追蹤實體所使用的變更追蹤邏輯以及允許設定自我追蹤實體狀態的擴充方法。<模型名稱>.Context.tt 檔案會產生具型別的 ObjectContext 和擴充類別,這個擴充類別包含 ObjectContext 和 ObjectSet 類別的 ApplyChanges 方法。這些方法會檢查自我追蹤實體圖形中所含的變更追蹤資訊,以便推斷要在資料庫中儲存變更所需執行的一組作業。如需詳細資訊,請參閱 ADO.NET Self-Tracking Entity Generator Template。
注意: |
---|
服務不應該信任來自不信任用戶端或通過不信任通道的擷取或更新資料要求。您必須驗證用戶端:應該使用安全通道或訊息封套。您必須驗證用戶端的更新或擷取資料要求,以便確保它們符合給定案例的預期和合法變更。 |
注意: |
---|
請避免使用機密資訊做為實體索引鍵 (例如身分證號碼)。這樣做可降低不小心將自我追蹤實體圖形中之機密資訊序列化至未完全信任之用戶端的可能性。使用獨立關聯時,與正在序列化之實體相關的實體的原始索引鍵也可能會傳送至用戶端。 |
自我追蹤實體擴充方法
下列擴充方法可套用至自我追蹤實體。如果您想要在一組實體而非單一實體上執行這些作業,請參閱使用自我追蹤實體集以了解詳細資訊。
StartTracking 方法
StartTracking 方法會指示實體的變更追蹤器開始記錄套用至實體的任何變更。這包括純量屬性、集合和其他實體之參考的變更。當自我追蹤實體透過 Windows Communication Foundation (WCF) 還原序列化至用戶端時,它們就會自動開始追蹤。在下列案例中,系統也會針對新建立的實體開啟追蹤:
在新實體與已經在追蹤變更的實體之間建立關聯性。
針對實體呼叫 MarkAs[State] 或 AcceptChanges 方法。
StopTracking 方法
StopTracking 方法會停止記錄變更。
MarkAs 方法
所有 MarkAs 方法都會開啟追蹤。這些擴充方法有助於將實體的狀態明確變更為 Added、Modified、Deleted 和 Unchanged。
MarkAs[State] 方法會傳回套用這些方法的相同實體 (已修改狀態)。下列範例會將實體的狀態修改為 Unchanged:
department.Course = new Course { CourseID = courseID }.MarkAsUnchanged();
MarkAsAdded 方法會將實體的狀態變更為 Added。新的自我追蹤實體會以 Added 狀態建立,但不啟用變更追蹤。
MarkAsDeleted 方法會將實體的狀態變更為 Deleted。這個方法也會清除標記為待刪除之實體的導覽屬性。如果導覽屬性指向參考物件,它就會設定為 null。如果導覽屬性代表集合,就會呼叫 Clear 方法。針對屬於集合一部分的物件呼叫 MarkAsDeleted 時,將會從集合中移除此物件。若要將集合中的每個物件都標記為已刪除,請在集合的複本中標記物件。若要取得集合的複本,請針對集合呼叫 ToArray() 或 ToList() 方法,如下列範例所示:
List<Course> courses = department.Courses.ToList();
foreach (var c in courses)
{
// Mark each course in the department as Deleted.
c.MarkAsDeleted();
}
MarkAsModified 方法會將實體的狀態變更為 Modified。此外,如果您修改已啟用變更追蹤之實體的屬性值,就會將實體的狀態設定為 Modified。
MarkAsUnchanged 方法會將實體的狀態變更為 Unchanged。此外,AcceptChanges 會清除實體的變更追蹤資訊並將其狀態移至 Unchanged。
AcceptChanges
AcceptChanges 方法會清除實體的變更追蹤資訊並將其狀態變更為 Unchanged。如果您想要重設關聯性的狀態,請針對參與關聯性的兩個實體呼叫 AcceptChanges。
ObjectContext 擴充方法
ApplyChanges 方法會檢查自我追蹤實體圖形中所含的變更追蹤資訊,並且推斷要在資料庫中反映變更所需執行的作業組。ApplyChanges 方法有兩種:其中一種方法適用於 ObjectContext,而另一種方法則適用於 ObjectSet。
注意: |
---|
若要避免將包含機密資料的例外狀況訊息傳播至用戶層,您應該在例外處理程式碼中包裝伺服器層之 ApplyChanges 和 SaveChanges 的呼叫。 |
使用自我追蹤實體時的考量
使用自我追蹤實體時,請考慮下列事項:
請確定您的用戶端專案具有包含實體類型之組件的參考。如果您只將服務參考加入至用戶端專案,用戶端專案將會使用 WCF Proxy 型別,而非實際的自我追蹤實體類型。這表示您將無法取得自動化通知功能,以便在用戶端上管理實體的追蹤。如果您故意不要加入實體類型,就必須在用戶端上手動設定變更追蹤資訊,讓變更傳送回服務。
服務作業的呼叫應該沒有狀態,並且建立物件內容的新執行個體。我們也建議您在 using 區塊中建立物件內容。
當您將已在用戶端上修改的圖形傳送至服務,然後想要繼續在用戶端上使用相同的圖形時,就必須手動逐一查看圖形,並且針對每個物件呼叫 AcceptChanges 方法,以便重設變更追蹤器。如果圖形中的物件包含屬性,而這些屬性含有資料庫產生的值 (例如識別或並行值),Entity Framework 就會在呼叫 SaveChanges 方法之後,將這些屬性的值取代成資料庫產生的值。您可以實作服務作業,以便將已儲存的物件或物件的產生屬性值清單傳回給用戶端。然後,用戶端就必須將物件執行個體或物件屬性值取代成服務作業所傳回的物件或屬性值。
合併來自多個服務要求的圖形時,可能會在產生的圖形中導入具有重複索引鍵值的物件。Entity Framework 不會在您呼叫 ApplyChanges 方法時移除具有重複索引鍵的物件,但是會改為擲回例外狀況。若要避免圖形具有重複的索引鍵值,請遵循下列部落格中描述的其中一種模式:自我追蹤實體:ApplyChanges 和重複的實體。
當您設定外部索引鍵屬性來變更物件之間的關聯性時,參考導覽屬性會設定為 null,而且不會同步處理至用戶端上的適當主體實體。當圖形附加至物件內容 (例如,在您呼叫 ApplyChanges 方法之後) 時,外部索引鍵屬性和導覽屬性就會進行同步處理。
如果您已經在外部索引鍵關聯性上指定了串聯刪除,但是參考導覽屬性卻沒有與適當的主體物件同步處理,此時就可能會發生問題。如果您刪除主體,此刪除作業將不會傳播至相依的物件。如果您已經指定了串聯刪除,請使用導覽屬性來變更關聯性,而非設定外部索引鍵屬性。
系統不會啟用自我追蹤實體來執行消極式載入。
從 [ADO.NET 自我追蹤實體產生器] 範本產生的程式碼不支援 ASP.NET 狀態管理物件的二進位序列化和序列化。不過,您可以自訂範本,以便加入二進位序列化支援。如需詳細資訊,請參閱使用二進位序列化和 ViewState 搭配自我追蹤實體。