エンティティ キーの使用 (Entity Framework)

各エンティティ型には、エンティティの 1 つ以上のスカラー プロパティに基づいたキーがあります。 キーは、概念モデルの Key 要素で定義されます。 リレーショナル データベースと同様に、これらのキー値は、指定されたエンティティの一意性を検証し、クエリのパフォーマンスを改善するために使用されます。 通常、キー プロパティは、元になるテーブルのキー列である、一意の値を保証するために制約されている ID 列またはその他の列にマップされます。 概念モデルでキーを定義する方法の詳細については、「Key 要素 (CSDL)」を参照してください。

オブジェクト クエリがオブジェクトを返すと、Entity Framework によってエンティティ オブジェクトが具体化されます。 また、エンティティ キーは EntityKey クラスのインスタンスに具体化されます。 この EntityKey クラスには、IEntityWithKey を実装するオブジェクトの EntityKey プロパティからアクセスできます。 また、Entity Data Model ツールによって生成されるすべてのデータ クラスの基本クラスである EntityObject によって、IEntityWithKey も実装されます。

Dd283139.note(ja-jp,VS.100).gif注 :
Entity Framework では、カスタム データ クラスに IEntityWithKey を実装する必要はありません。

EntityKey オブジェクトの構築と使用

EntityKey オブジェクトは、EntitySetName プロパティ、EntityContainerName プロパティ、および 1 つ以上のキーと値のペアの配列で構成されます。 キーと値のペアは、プロパティ名とプロパティ値で構成されます。 キーと値のペアは、EntityKeyValues プロパティの 1 つ以上の EntityKeyMember オブジェクトとして指定します。

Dd283139.note(ja-jp,VS.100).gif注 :
EntityKey コンストラクターのいずれかを使用する場合、qualifiedEntitySetName パラメーターに渡される文字列値は、"EntityContainerName.EntitySetName" のように、EntitySetName の前に EntityContainerName が付加されます。

また、デタッチされたオブジェクトの EntityKey を取得するために、ObjectContextCreateEntityKey メソッドを使用することもできます。 オブジェクトに有効なキーがない場合、オブジェクト コンテキストによって、指定したオブジェクトの新しい EntityKey インスタンスが構築されます。 詳細については、「方法: EntityKey を作成する (Entity Framework)」を参照してください。

エンティティ キーはエンティティを一意に識別するので、残りのオブジェクト値がデータ ソースから取得されていない場合でも、キーのみを持つエンティティを作成して、オブジェクトをオブジェクト コンテキストにアタッチできます。 詳細については、「関連するオブジェクトをアタッチする方法 (Entity Framework)」を参照してください。 また、エンティティ キーを使用して、オブジェクト コンテキストまたはデータ ソースからオブジェクトを取得することもできます。 詳細については、「キーを使用して特定のオブジェクトを返す方法 (Entity Framework)」を参照してください。

固定長エンティティ キー

Entity Framework は、EntityKey の値に基づいて ID 解決を実行します。この値は、データベースの主キーに対応しています。 既に ObjectContext に存在する EntityKey を持つオブジェクトがクエリによって返される場合、新しいオブジェクトは作成されません。 データベース内の固定サイズの列を操作していて、データベースで指定されたサイズよりも短い値を保持している場合、データベースによっては、固定サイズ型にスペースまたはゼロが埋め込まれます。 SQL Server では、固定サイズの文字列型の末尾にスペースが埋め込まれます。 固定サイズ型 (バイナリや文字など) が主キーとして使用されている場合、ID 解決の問題が発生する可能性があります。

例を次に示します。 Product テーブルで、主キーにサイズ 10 の固定長の列を使用しています。 EntityKeyAB100 の Product オブジェクトが作成され、ObjectContext に追加されます。 オブジェクトがデータベースに保存されるときに、列が固定サイズで、保存される値がデータベースのサイズよりも短いため、キーの末尾にスペースが埋め込まれます。 SQL Server が AB100 と埋め込まれた文字列を照合するので、AB100EntityKey を持つオブジェクトの後続のクエリによって、別の 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 に設定されます。

対応する列値がデータベースで生成された ID である場合、ストレージ モデルのエンティティの Property 要素の StoreGeneratedPattern 属性を Identity に設定します。 Entity Data Model ツールによって既存のデータ ソースからデータ モデルが生成されると、StoreGeneratedPattern 属性は、データ ソースの ID または計算列を表す各 Property 要素 (CSDL) 要素に追加されます。 Entity Framework では、SaveChanges が呼び出されると、一時キーのプロパティ値が、データ ソースによって生成された ID 値と置換されます。

次に、一時キーと、サーバー生成値を含んでいる永久キーを置換する内部プロセスを詳しく示します。

  1. エンティティ オブジェクトが構築されます。

    この時点で、すべてのキー プロパティは、null または 0 の既定値に設定されます。

  2. ObjectContext または ObjectSetAddObject メソッドを呼び出すか、リレーションシップの "多" の側の End でオブジェクトのコレクションにオブジェクトを追加すると、新しいオブジェクトが ObjectContext に追加されます。

    この時点で、Entity Framework によって、オブジェクトを ObjectStateManager に格納するために使用される一時キーが生成されます。

  3. SaveChangesObjectContext で呼び出されます。

    INSERT ステートメントが、Entity Framework によって生成され、データ ソースで実行されます。

  4. INSERT 操作が正常に実行された場合、サーバー生成値が ObjectStateEntry に書き戻されます。

  5. ObjectStateEntry が、サーバー生成値でオブジェクトを更新します。

  6. ObjectStateEntryAcceptChanges が呼び出されると、新しいサーバー生成値を使用して永久 EntityKey が計算されます。

    Dd283139.note(ja-jp,VS.100).gif注 :
    AcceptChanges は、SaveChanges の実行が終了した時点で、または SaveChanges メソッドが AcceptAllChangesAfterSave フラグを使用して呼び出されたとき、自動的に呼び出されます。

  7. ObjectStateManager が、一時キーのすべてのインスタンスを新しい永久キーと置換します。

GUID プロパティ値

Entity Framework は、一意性を保つために Guid 型を返すエンティティ プロパティをサポートしています。

Entity Framework では、サーバー生成の GUID 型 ID 値がサポートされますが、プロバイダーは、サーバー生成の ID 値を行の挿入後に返す必要があります。 SQL Server では、SQL Server 2005 以降、サーバー生成 GUID 型を OUTPUT 句で返すことができるようになりました。 プロバイダーが OUTPUT 句と同等の機能をサポートしていない場合は、クライアント側で新しいオブジェクトの GUID 値を生成します。 このためには、SavingChanges イベントを処理して、Added 状態のエンティティ オブジェクトに新しい GUID 値を生成することをお勧めします。 詳細については、「変更を保存するときにビジネス ロジックを実行する方法 (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」を参照してください。

このセクションの内容

方法: EntityKey を作成する (Entity Framework)

参照

処理手順

方法: EntityKey を作成する (Entity Framework)

その他のリソース

Entity Data Model Tools