オブジェクトのアタッチとデタッチ (Entity Framework)
Entity Framework では、オブジェクトをオブジェクト コンテキストにアタッチしたり、オブジェクト コンテキストからデタッチしたりできます。 オブジェクト コンテキストにアタッチされているオブジェクトは、オブジェクト コンテキストによって追跡および管理されます。 デタッチされたオブジェクトはオブジェクト コンテキストによって参照されなくなるので、そのリソースを .NET Framework で再利用できます。 このトピックでは、オブジェクトのアタッチおよびデタッチの方法と、それに関する注意事項について説明します。
オブジェクトのアタッチ
Entity Framework では、オブジェクト コンテキスト内でクエリを実行すると、返されたオブジェクトがそのオブジェクト コンテキストに自動的にアタッチされます。 クエリ以外のソースから取得したオブジェクト コンテキストにオブジェクトをアタッチすることもできます。 以前にデタッチされているオブジェクト、NoTracking クエリによって返されたオブジェクト、またはオブジェクト コンテキストの外部で取得したオブジェクトなどもアタッチできます。 さらに、ASP.NET アプリケーションのビュー ステートに保存されていたオブジェクトや、リモート メソッド呼び出しまたは Web サービスによって返されたオブジェクトもアタッチできます。
オブジェクトをオブジェクト コンテキストにアタッチするには、次のいずれかのメソッドを使用します。
メンバー | Description |
---|---|
System.Data.Objects.ObjectSet.AddObject( または System.Data.Objects.ObjectContext.AddObject(System.String,System.Object) |
オブジェクトとその関連オブジェクトを ObjectContext に追加し、エンティティ オブジェクトを Added 状態に設定します。 この状態では、一意のキー値を持つためにエンティティ オブジェクトは必要ありません。 一時的なキー値がキーのプロパティに割り当てられ、オブジェクトの保存後にデータ ソースが生成した値で更新されます。 オブジェクトを追加後、エンティティ オブジェクトの状態を適切に変更します。 |
System.Data.Objects.ObjectSet.Attach( または System.Data.Objects.ObjectContext.Attach(System.Data.Objects.DataClasses.IEntityWithKey) and |
オブジェクトを ObjectContext に追加し、オブジェクトを Unchanged 状態に設定します。 In the Unchanged state, the Entity Framework treats the entity key values as final. 特定の型の複数のエンティティに同じキーの値がある場合は、Entity Framework は例外をスローします。 例外を回避するには、AddObject メソッドを使用してデタッチされたオブジェクトをアタッチし、適切な状態に変更します。 |
オブジェクトは Unchanged 状態でオブジェクト コンテキストにアタッチされます。 オブジェクトがデタッチ状態で変更されたことがわかっているために、オブジェクトの状態またはリレーションシップを変更する必要がある場合は、次のいずれかのメソッドを使用します。
メンバー | Description |
---|---|
エンティティまたはリレーションシップを新しい状態 (Added や Modified など) に変更します。 この変更を行うと、エンティティが参加しているリレーションシップに影響を与える場合があります。 たとえば、エントリを Added 状態に移動すると、変更されていないリレーションシップも Added 状態に移動します。 同様に、エンティティに Modified のマークを付けると、すべてのスカラー値にも Modified のマークが付きます。 You may also use the ChangeState method of the ObjectStateEntry. |
|
2 つのエンティティ間の既存のリレーションシップを、指定した状態に変更します。 エンティティ間にリレーションシップがない場合は、指定された状態の新しいリレーションシップがこのメソッドによって作成されます。 このメソッドは、外部キーの関連付けに基づくリレーションシップではサポートされていません。 詳細については、「リレーションシップの定義と管理 (Entity Framework)」を参照してください。 You may also use the ChangeObjectState method of the ObjectStateEntry. |
|
ChangeState |
このメソッドは、ObjectStateEntry がオブジェクトかリレーションシップであるかによって、ChangeObjectState や ChangeRelationshipState と同様に動作します。 |
個々のプロパティを Modified 状態に設定します。 エンティティ全体を変更済みに設定するのではなく、変更されたプロパティがわかっている場合に、このメソッドを使用します。 |
アタッチされるオブジェクトに更新済みのプロパティ値がある場合は、次のいずれかのメソッドを使用します。
メンバー | Description |
---|---|
System.Data.Objects.ObjectSet.ApplyCurrentValues( または System.Data.Objects.ObjectContext.ApplyCurrentValues.String, |
指定されたオブジェクトのスカラー値を、同じキーを持つ ObjectContext のオブジェクトにコピーします。 元の値と異なる値は変更済みとしてマークされます。 現在の値を使用しているグラフに元の値を適用するには、ApplyOriginalValues メソッドを呼び出します。 You may also use the ApplyCurrentValues method of the ObjectStateEntry. |
System.Data.Objects.ObjectSet.ApplyOriginalValues( または System.Data.Objects.ObjectContext.ApplyOriginalValues.String, |
指定されたオブジェクトのスカラー値を、同じキーを持つ ObjectContext のオブジェクトの一連の元の値にコピーします。 現在の値と異なる値は変更済みとしてマークされます。 You may also use the ApplyOriginalValues method of the ObjectStateEntry. |
SetModifiedProperty |
個々のプロパティを Modified 状態に設定します。 エンティティ全体を変更済みに設定するのではなく、変更されたプロパティがわかっている場合に、このプロパティを使用します。 |
この ObjectStateEntry に関連付けられているオブジェクトの元の値の更新可能なバージョンを表す OriginalValueRecord インスタンスを取得します。 返された OriginalValueRecord インスタンスを使用して、オブジェクトの元のプロパティを個別に読み取ったり更新したりします。 |
|
この ObjectStateEntry に関連付けられているオブジェクトの現在の値を表す CurrentValueRecord インスタンスを取得します。 返された CurrentValueRecord インスタンスを使用して、オブジェクトの現在のプロパティを個別に読み取ったり更新したりします。 |
オブジェクトのアタッチに関する注意点
オブジェクト コンテキストにオブジェクトをアタッチする際は、次の点を考慮してください。
アタッチされるオブジェクトに関連オブジェクトがある場合、それらのオブジェクトもオブジェクト コンテキストにアタッチされます。
アタッチされたオブジェクトがデータ ソースに存在しない場合、そのオブジェクトは SaveChanges の実行時に追加されません。 この場合、プロパティに変更が加えられると、SaveChanges の実行時にサーバーで例外が発生します。 オブジェクトを追加するには、System.Data.Objects.ObjectSet.AddObject( または System.Data.Objects.ObjectContext.AddObject(System.String,System.Object) を使用します。
アタッチされるオブジェクトが他のオブジェクトに関連している場合、「リレーションシップの定義と管理 (Entity Framework)」で説明されている次のいずれかの方法でリレーションシップを明示的に定義する必要があります。 For more information, see 関連するオブジェクトをアタッチする方法 (Entity Framework).
Attach メソッドに渡されるオブジェクトには、有効な EntityKey 値が必要です。 オブジェクトに有効な EntityKey 値がない場合は、AttachTo メソッドを使用してエンティティ セットの名前を指定します。
アタッチされるオブジェクトと同じ EntityKey がオブジェクト コンテキストに別のオブジェクトとして既に存在する場合は、InvalidOperationException が発生します。 コンテキスト内のオブジェクトが同じキーを持っていても、Added 状態にある場合、このエラーは発生しません。
オブジェクトのデタッチ
Entity Framework アプリケーションでは、オブジェクトをオブジェクト コンテキストからデタッチできます。 同じオブジェクト コンテキスト内で繰り返しクエリを実行すると、オブジェクト コンテキストに必要なメモリが増加するため、オブジェクトをデタッチしてリソースを節約します。 オブジェクトをオブジェクト コンテキストにアタッチされたままにするには、NoTracking の MergeOption 値を使用してクエリを実行するか、次の例に示すように、System.Data.Objects.ObjectSet.Detach( メソッドまたは System.Data.Objects.ObjectContext.Detach(System.Object) メソッドを呼び出し、デタッチするオブジェクトへの参照を渡してオブジェクトをデタッチします。
' Detach the first SalesOrderDetail in the collection.
context.Detach(order.SalesOrderDetails.First())
// Detach the first SalesOrderDetail in the collection.
context.Detach(order.SalesOrderDetails.First());
オブジェクトのデタッチに関する注意点
オブジェクトをデタッチする際は、次の点に注意してください。
Detach は、メソッドに渡される特定のオブジェクトにのみ影響します。 オブジェクト コンテキスト内で、デタッチされるオブジェクトに関連オブジェクトがある場合、それらの関連オブジェクトはデタッチされません。
独立アソシエーションでは、デタッチされたオブジェクトのリレーションシップ情報は維持されません。
デタッチされたオブジェクトのオブジェクト状態情報は維持されません。 これには追跡された変更および一時キー値が含まれます。
オブジェクトのデタッチは、データ ソース内のデータには影響しません。
識別リレーションシップ内の連鎖削除ディレクティブおよび参照に関する制約は、デタッチ操作中には適用されません。
操作を実行するために追加の処理が必要な場合は、オブジェクトのデタッチを検討する必要があります。 異なるデータ セットを含む新しいフォームの表示などのユーザー データのスコープが変更された場合、既存の ObjectContext からオブジェクトをデタッチするのではなく、新しい ObjectContext インスタンスを作成することを検討してください。
詳細については、「オブジェクト コンテキストからオブジェクトをデタッチする方法 (Entity Framework)」を参照してください。
このセクションの内容
関連するオブジェクトをアタッチする方法 (Entity Framework)
デタッチされたオブジェクト対して行われた変更を適用する方法 (Entity Framework)
オブジェクト コンテキストからオブジェクトをデタッチする方法 (Entity Framework)