オブジェクトの状態と変更の追跡 (LINQ to SQL)
更新 : November 2007
LINQ to SQL オブジェクトは常に、いずれかの状態にあります。たとえば、LINQ to SQL が新しいオブジェクトを作成すると、そのオブジェクトは Unchanged 状態です。ユーザーが作成する新しいオブジェクトは DataContext にとって不明であり、Untracked 状態です。SubmitChanges が正常に実行されると、すべてのオブジェクトが LINQ to SQL にとって既知となり、Unchanged 状態になります (データベースから削除されたオブジェクトは例外です。これは Deleted 状態であり、DataContext インスタンスの中で使用できません)。
オブジェクトの状態
LINQ to SQL オブジェクトで有効な状態を次の表に示します。
状態 |
説明 |
---|---|
Untracked |
LINQ to SQL によって追跡されないオブジェクト。具体的には次のものがあります。
|
Unchanged |
現在の DataContext を使用して取得され、作成後に変更された履歴がないオブジェクト。 |
PossiblyModified |
DataContext にアタッチされているオブジェクト。詳細については、「N 層アプリケーションでのデータ取得および CUD 操作 (LINQ to SQL)」を参照してください。 |
ToBeInserted |
現在の DataContext を使用して取得されていないオブジェクト。この場合、SubmitChanges 中にデータベースの INSERT が発生します。 |
ToBeUpdated |
取得後に変更された履歴があるオブジェクト。この場合、SubmitChanges 中にデータベースの UPDATE が発生します。 |
ToBeDeleted |
削除がマークされているオブジェクト。SubmitChanges 中にデータベースの DELETE が発生します。 |
Deleted |
データベース内で削除されたオブジェクト。これは最後の状態であり、次の状態に移行できません。 |
オブジェクトの挿入
InsertOnSubmit を使用して、Inserts を明示的に要求できます。または、LINQ to SQL は、更新する必要がある既知のオブジェクトの 1 つに接続しているオブジェクトを見つけることによって、Inserts を推論できます。たとえば、Untracked オブジェクトを EntitySet<TEntity> に追加するか、EntityRef<TEntity> を Untracked オブジェクトに設定すると、グラフ内の追跡オブジェクトを通じて、Untracked オブジェクトにアクセスできるようになります。SubmitChanges の実行中、LINQ to SQL は追跡オブジェクトをスキャンして、追跡されていないアクセス可能な永続オブジェクトを見つけます。このようなオブジェクトは、データベースへの挿入候補です。
また、継承階層内のクラスの場合、InsertOnSubmit(o) は、識別子として指定されているメンバの値が、オブジェクト o の型に一致するように設定します。既定の識別子の値の型が一致する場合、この操作によって、識別子の値が既定値で上書きされます。詳細については、「継承のサポート (LINQ to SQL)」を参照してください。
重要 : |
---|
Table に追加されたオブジェクトは、ID キャッシュにはありません。ID キャッシュは、データベースから取得されたもののみを反映します。InsertOnSubmit を呼び出した後、SubmitChanges が正常終了するまで、追加されたエンティティはデータベースに対するクエリで使用されません。 |
オブジェクトの削除
適切な Table<TEntity> で DeleteOnSubmit(o) を呼び出すことにより、追跡オブジェクト o に削除のマークを付けることができます。LINQ to SQL では、EntitySet<TEntity> からのオブジェクトの削除は更新操作と見なされ、対応する外部キー値は null に設定されます。操作の対象 (o) はテーブルから削除されません。たとえば、cust.Orders.DeleteOnSubmit(ord) は、外部キー ord.CustomerID を null に設定することによって cust と ord のリレーションシップが切断される更新を表します。ord に対応する行の削除は行われません。
テーブルからオブジェクトを削除すると (DeleteOnSubmit)、LINQ to SQL は次の処理を実行します。
SubmitChanges を呼び出すときに、そのオブジェクトに対して DELETE 操作が実行されます。
関連オブジェクトが読み込まれているかどうかにかかわらず、関連オブジェクトに削除は反映されません。特に、リレーションシップ プロパティを更新するために関連オブジェクトが読み込まれることはありません。
SubmitChanges が正常に実行されると、オブジェクトは Deleted 状態に設定されます。その結果、その DataContext で、オブジェクトまたはその id を使用することはできません。データベース内でオブジェクトが削除された後でも、DataContext インスタンスによって保持される内部キャッシュは、取得されたオブジェクトや新規として追加されたオブジェクトを消去しません。
DataContext によって追跡されたオブジェクトでのみ、DeleteOnSubmit を呼び出すことができます。Untracked オブジェクトの場合は、DeleteOnSubmit を呼び出す前に Attach を呼び出す必要があります。Untracked オブジェクトで DeleteOnSubmit を呼び出すと、例外がスローされます。
メモ : |
---|
テーブルからオブジェクトを削除すると、SubmitChanges が呼び出されたときに、対応する SQL DELETE コマンドが LINQ to SQL によって生成されることになります。この処理によって、キャッシュからオブジェクトが削除されたり、関連オブジェクトに削除が反映されることはありません。 削除されたオブジェクトの id を再要求するには、新しい DataContext インスタンスを使用します。関連オブジェクトをクリーンアップするには、データベースの連鎖削除機能を使用するか、関連オブジェクトを手動で削除します。 関連オブジェクトは、データベースの場合とは異なり、特別な順序で削除する必要はありません。 |
オブジェクトの更新
変更の通知を確認することで、Updates を検出できます。通知は、プロパティ Set アクセス操作子の PropertyChanging イベントを通じて提供されます。LINQ to SQL は、オブジェクトへの最初の変更が通知されると、オブジェクトのコピーを作成し、オブジェクトを、Update ステートメントを生成する候補と見なします。
INotifyPropertyChanging を実装していないオブジェクトの場合、LINQ to SQL は、オブジェクトが最初に実体化されたときの値のコピーを保持します。SubmitChanges を呼び出すと、LINQ to SQL は、現在の値と元の値を比較して、オブジェクトが変更されたかどうかを判断します。
リレーションシップの更新の場合、子から親への参照 (つまり、外部キーに対応する参照) が基準と見なされます。逆方向 (つまり、親から子) の参照はオプションです。リレーションシップ クラス (EntitySet<TEntity> および EntityRef<TEntity>) は、一対多および一対一のリレーションシップで双方向の参照が一致することを保証します。オブジェクト モデルが EntitySet<TEntity> または EntityRef<TEntity> を使用していない場合、かつ、逆方向の参照が存在する場合は、ユーザーが、リレーションシップが更新されるときに前方参照と一致するようにする必要があります。
要求される参照と対応する外部キーの両方を更新する場合は、両者が一致する必要があります。SubmitChanges を呼び出したときに 2 つが同期しない場合は、InvalidOperationException 例外がスローされます。外部キー値を変更するだけで、基になる行を更新することはできますが、オブジェクト グラフの接続と、リレーションシップの双方向の一貫性を保持するには、参照を変更する必要があります。