分享方式:


物件狀態和變更追蹤

LINQ to SQL 物件一律會參與某種「狀態」。 例如,LINQ to SQL 建立新物件時,該物件會是 Unchanged 狀態。 您自己建立新的物件時,由於 DataContext 還不知道該物件,所以該物件會是 Untracked 狀態。 順利執行 SubmitChanges 之後,LINQ to SQL 得知的所有物件都會是 Unchanged 狀態。 (唯一的例外是已順利從資料庫中刪除的物件,這些物件是 Deleted 狀態,而且無法在該 DataContext 執行個體中使用)。

物件狀態

下表列出 LINQ to SQL 物件的可能狀態。

State 描述
Untracked LINQ to SQL 未追蹤的物件。 範例包括如下:

- 未透過目前 DataContext 查詢的物件 (例如新建立的物件)。
- 透過還原序列化建立的物件
- 透過不同 DataContext 查詢的物件。
Unchanged 使用 DataContext 擷取而且已知自建立後尚未修改的物件。
PossiblyModified 「附加」DataContext 的物件。 如需詳細資訊,請參閱多層式架構應用程式中的資料擷取和 CUD 作業 (LINQ to SQL)
ToBeInserted 未使用目前 DataContext 擷取的物件。 這會導致 INSERT 期間執行資料庫 SubmitChanges 動作。
ToBeUpdated 已知自擷取後曾經修改的物件。 這會導致 UPDATE 期間執行資料庫 SubmitChanges 動作。
ToBeDeleted 標記要刪除的物件,這會導致在 DELETE 期間執行資料庫 SubmitChanges 動作。
Deleted 已在資料庫中刪除的物件。 這個狀態為最終狀態,不允許進行其他轉換。

插入物件

您可以使用 Inserts 明確要求執行 InsertOnSubmit。 此外,當 LINQ to SQL 發現有物件連接至其中一個必須要更新的已知物件時,即會推斷要執行 Inserts。 例如,如果您將 Untracked 物件新增至 EntitySet<TEntity> 或將 EntityRef<TEntity> 設為 Untracked 物件,即可透過圖形中的已追蹤物件讓 Untracked 物件可受接觸。 處理 SubmitChanges 時,LINQ to SQL 會周遊已追蹤的物件,並且探索任何未受追蹤的可接觸持續性物件。 這些物件會成為等候插入資料庫中的項目。

對於在繼承階層架構中的類別,InsertOnSubmit(o) 也會將類別中已指定為「鑑別子」成員的值,設定為符合物件 o 的類型。 當型別符合預設鑑別子值時,這個動作會導致鑑別子值遭預設值覆寫。 如需詳細資訊,請參閱繼承支援

重要

已加入至 Table 的物件不會出現在識別 (Identity) 快取中。 識別快取只會反映從資料庫擷取的物件。 呼叫 InsertOnSubmit 之後,除非 SubmitChanges 順利完成,否則加入的實體都不會出現在對資料庫的查詢中。

刪除物件

您可以在適當的 o 上呼叫 DeleteOnSubmit(o),將已追蹤的物件 Table<TEntity> 標記為要刪除。 LINQ to SQL 會將從 EntitySet<TEntity> 中移除物件的動作視為更新作業,而且對應的外部索引鍵值會設為 Null。 作業的目標 (o) 並不會從其資料表中刪除。 例如,cust.Orders.DeleteOnSubmit(ord) 所表示的更新,是將外部索引鍵 cust 設為 null 來切斷 ordord.CustomerID 之間的關聯性 (Relationship)。 這並不會刪除 ord 所對應的資料列。

從資料表中刪除物件 (DeleteOnSubmit) 時,LINQ to SQL 會執行下列處理:

  • 呼叫 SubmitChanges 時,會對該物件執行 DELETE 作業。

  • 不論是否已載入相關物件,移除作業都不會擴及相關物件。 具體來說,並不會載入相關物件來更新關聯性屬性。

  • 順利執行 SubmitChanges 之後,物件會設為 Deleted 狀態。 因此,您無法使用該物件也無法使用其在該 id 中的 DataContext。 由 DataContext 執行個體維護的內部快取並不會刪除已擷取或新加入的物件,即使物件已從資料庫中刪除也一樣。

您只可以對 DeleteOnSubmit 所追蹤的物件呼叫 DataContext。 至於 Untracked 物件,您必須先呼叫 Attach,然後再呼叫 DeleteOnSubmit。 對 DeleteOnSubmit 物件呼叫 Untracked 會擲回例外狀況。

注意

從資料表中移除物件,會告知 LINQ to SQL 要在執行 SubmitChanges 時產生對應的 SQL DELETE 命令。 這個動作並不會從快取中移除物件,也不會將刪除作業擴及相關的物件。

若要回收已刪除物件的 id,請使用新的 DataContext 執行個體。 若要清除相關的物件,您可以使用資料庫的「串聯刪除」功能,或自行手動刪除相關物件。

刪除相關的物件時不必按照任何特定順序 (不像在資料庫中)。

更新物件

您可以藉由觀察有沒有變更告知來偵測 Updates。 告知是透過屬性 setter 中的 PropertyChanging 事件來提供。 當 LINQ to SQL 獲知物件第一次受到變更時,它會建立物件的複本並且將此物件列為要產生 Update 陳述式的對象。

如果是未實作 INotifyPropertyChanging 的物件,LINQ to SQL 會保留物件初次具體化時所含的值複本。 當您呼叫 SubmitChanges 時,LINQ to SQL 會比較目前的值與原始值,以判斷物件是否已變更。

如果是要更新關聯性,則子系 (Child) 對父代 (Parent) 的參考 (也就是對應於外部索引鍵的參考) 會是最主要的參考。 反方向 (也就是父代對子系的參考) 的參考則為選擇性的。 關聯性類別 (EntitySet<TEntity>EntityRef<TEntity>) 會保證一對多和一對一關聯性中的雙向參考都是一致的。 如果物件模型未使用 EntitySet<TEntity>EntityRef<TEntity>,而反向參考存在,您就有責任使它在更新關聯性後,與向前參考 (Forward Reference) 一致。

如果要同時更新必要的參考和對應的外部索引鍵,就必須確定兩者一致。 如果在您呼叫 InvalidOperationException 時這兩者並未同步,則會擲回 SubmitChanges 例外狀況。 雖然只要變更外部索引鍵值就能更新基礎資料列,但您仍應該變更參考,以維護物件圖形中的連接並保持雙向關聯性的一致性。

另請參閱