使用實體索引鍵 (Entity Framework)
每個實體類型都有一個以實體的一個或多個純量屬性為基礎的索引鍵。 索引鍵是由概念模型中的 Key 項目來定義。 就像在關聯式資料庫中一樣,這些索引鍵值是用來驗證指定之實體的唯一性及改善查詢效能。 索引鍵屬性通常對應至基礎資料表中的索引鍵資料行,可能是識別資料行或已限制為保證唯一值的某個其他資料行。 如需概念模型中如何定義索引鍵的詳細資訊,請參閱 Key 項目 (CSDL)。
當物件由物件查詢傳回時,Entity Framework 會具體化實體物件。 同時還會將實體索引鍵具體化為 EntityKey 類別的執行個體。 您可以從會實作 IEntityWithKey 之物件的 EntityKey 屬性存取這個 EntityKey。 EntityObject 是 實體資料模型 工具所產生之所有資料類別的基底類別,它也會實作 IEntityWithKey。
注意: |
---|
Entity Framework 不需要您實作自訂資料類別中的 IEntityWithKey。 |
建構及使用 EntityKey 物件
EntityKey 物件是由 EntitySetName 和 EntityContainerName 屬性,以及一個或多個索引鍵/值組的陣列所組成。 索引鍵/值組是由屬性名稱和屬性值組成。 您將索引鍵/值組在 EntityKeyValues 屬性中當成一個或多個 EntityKeyMember 物件來提供。
注意: |
---|
當您使用其中一個 EntityKey 建構函式時,提供給 qualifiedEntitySetName 參數的字串值是由 EntityContainerName 附加在前的 EntitySetName,就像 "EntityContainerName.EntitySetName" 中的情況。 |
您也可以使用 ObjectContext 上的 CreateEntityKey 方法來取得已中斷連結之物件的 EntityKey。 如果物件沒有有效的索引鍵,物件內容會為指定的物件建構新的 EntityKey 執行個體。 如需詳細資訊,請參閱 HOW TO:建立 EntityKey (Entity Framework)。
因為實體索引鍵會唯一識別實體,您可以只使用該索引鍵來建立實體,並將物件附加至物件內容,即使其餘物件值並非擷取自資料來源也一樣。 如需詳細資訊,請參閱 HOW TO:附加相關的物件 (Entity Framework)。 也可以使用實體索引鍵,從物件內容或資料來源擷取物件。 如需詳細資訊,請參閱 HOW TO:使用特定物件的索引鍵傳回此物件 (Entity Framework)。
固定長度的實體索引鍵
Entity Framework 會根據 EntityKey 的值 (對應至資料庫中的主索引鍵) 來執行識別解析。 如果查詢傳回具有 EntityKey (已存在 ObjectContext 中) 的物件,便不會建立新物件。 如果您要使用資料庫中的固定大小資料行,而且要保存的值短於資料庫中的指定大小,某些資料庫會使用空格或零來填補固定大小類型。 不過,SQL Server 會使用後端空格來填補固定大小的字串類型。 當您使用固定大小類型 (例如二進位或 Char) 做為主索引鍵時,它可能會產生識別解析問題。
請參考下列範例。 Product 資料表的主索引鍵具有大小為 10 的固定長度資料行。 已建立具有 EntityKey AB100
的 Product 物件,並將它加入至 ObjectContext。 當此物件儲存至資料庫時,因為資料行是固定的大小,而且儲存的值短於資料庫中的大小,所以索引鍵會使用後端空格填補。 因為 SQL Server 會將 AB100
與填補的字串加以比對,所以針對 EntityKey 為 AB100
之物件進行的後續查詢將傳回具有不同 EntityKey (AB100
後面加後端空格) 的物件。 Entity Framework 不會修剪或填補屬性的值。 結果會將新物件 (具有 EntityKey AB100
後面加後端空格) 加入至 ObjectContext。
Product p1= new Product
{
ProductID = "AB100",
Description = "New product"
};
// An object with EntityKey "AB100" is added to ObjectContext. ctx.Products.AddObject(p1);
// The object is saved in the database with a primary key of
// "AB100 " because the column is of a fixed size. ctx.SaveChanges();
// When a query is executed for an object with key "AB100", SQL Server // matches the key to "AB100 ". The result is that a new object
// with EntityKey "AB100 " is added to ObjectContext. Product p2 = ctx.Products.First(p => p.ProductCode == "AB100");
若要避免這個不想要的行為,您可以執行下列其中一個動作:
在資料庫中使用可變長度的類型而非固定長度的類型。
在用戶端上使用後端空格或零來填補 EntityKey 的值。 您可以使用 PadRight 方法,以空格填補字串。
實體索引鍵和加入的物件
建立新實體時,Entity Framework 會定義暫時索引鍵,並將 IsTemporary 屬性設定為 true。 當您呼叫 SaveChanges 方法時,Entity Framework 會指派一個永久索引鍵並將 IsTemporary 屬性設定為 false。
如果對應的資料行值是資料庫中產生的識別,請將儲存體模型中實體之 Property 項目的 StoreGeneratedPattern 屬性設定為 Identity。 當 實體資料模型 工具從現有的資料來源產生資料模型時,StoreGeneratedPattern 屬性會加入至每個代表資料來源中的識別或計算過之資料行的 Property 項目 (CSDL) 項目。 在呼叫 SaveChanges 之後,Entity Framework 會使用由資料來源產生的識別值來取代暫存索引鍵中的屬性值。
下面詳述使用永久索引鍵 (內含伺服器產生的值) 來取代暫存索引鍵的內部程序:
已建構實體物件。
此時,索引鍵屬性全都有預設值,可能是 null 或 0。
新物件會加入至 ObjectContext,可能透過呼叫 ObjectContext 或 ObjectSet 上的 AddObject 方法,或在關聯性的「多」端上將物件加入至物件集合等方式。
此時,Entity Framework 會產生一個暫存索引鍵,用來在 ObjectStateManager 中存放物件。
SaveChanges 會在 ObjectContext 上呼叫。
INSERT 陳述式是由 Entity Framework 產生並針對資料來源執行。
如果 INSERT 作業成功,伺服器產生的值會寫回 ObjectStateEntry。
ObjectStateEntry 會使用伺服器產生的值來更新物件。
在 ObjectStateEntry 上呼叫 AcceptChanges 時,會使用新的伺服器產生之值來計算永久的 EntityKey。
注意: 在 SaveChanges 執行終結時,或使用 AcceptAllChangesAfterSave 旗標呼叫 SaveChanges 方法時,會自動呼叫 AcceptChanges。 ObjectStateManager 會使用新的永久索引鍵來取代暫存索引鍵的所有執行個體。
GUID 屬性值
Entity Framework 支援會傳回 Guid 型別以確保唯一性的實體屬性。
Entity Framework 支援伺服器產生的 GUID 型別識別值,但是提供者必須能夠在插入資料列之後,傳回伺服器產生的識別值。 從 SQL Server 2005 開始,SQL Server 可以透過 OUTPUT 子句 (英文) 傳回伺服器產生的 GUID 型別。 如果提供者不支援與 OUTPUT 子句相等的功能,則在用戶端上為新物件產生 GUID 值。 若要這麼做,我們建議處理 SavingChanges 事件來為處於 Added 狀態的任何實體物件產生新的 GUID 值。 如需詳細資訊,請參閱 HOW TO:在儲存變更時執行商務邏輯 (Entity Framework)。
使用Entity Data Model Wizard或Update Model Wizard產生或更新資料模型時,會自動針對資料來源中的 uniqueidentifier 具型別資料行產生實體類型的 GUID 屬性。 資料來源也可能使用 16 位元二進位資料行,儲存 GUID 值。 因為在資料來源中,該工具會為每個二進位資料行產生二進位屬性,所以您必須手動編輯 .edmx 檔案以更新這類資料行,使其對應至 GUID 屬性。 如需詳細資訊,請參閱 How to: Map a GUID Property to a Binary Column。
本節內容
HOW TO:建立 EntityKey (Entity Framework)
另請參閱
工作
HOW TO:建立 EntityKey (Entity Framework)