削除動作のカスタマイズ
要素を削除すると通常は関連要素を削除します。すべての関係は環境に接続して子要素をすべて削除されます。この動作は 削除の伝達と いう名前です。たとえば追加の関連要素が削除されることを配置するために delete 伝達をカスタマイズできます。プログラム コードを記述することにより伝達を削除するとモデルの状態に応じてら決してもできます。には他の変更削除が発生する可能性があります。
ここでは、次の内容について説明します。
削除の動作を設定します。
伝達を設定するロールのオプションを削除します。
– 削除するクロージャのオーバーライド 削除が隣接する要素の削除が発生することがあります。この方法を使用します。
– OnDeleting を使用してOnDeleted 内に応答がストアの外部の値の更新などの他のアクションを含めることができます。これらのメソッドを使用します。
–規則を反映する 削除規則 1 の変更が必要になる可能性のあるストア内の種類の更新を使用します。
remove イベント – Visual Studio の他のドキュメントにストアの外部の更新たとえば反映させるためにストアのイベントを使用します。
– UnMerge 親に子要素をアタッチしたマージ操作を元に戻すには UnMerge 操作を使用します。
既定の削除の動作
既定では以下の規則を削除したり伝達を当てています :
要素が削除されるとすべての埋め込み要素も削除されます。埋め込み要素はこの要素にソースの関係を埋め込むことでターゲット要素です。たとえば曲からアルバムに埋め込む関係がある場合は特定のアルバムが削除されると曲がすべて削除されます。
曲を削除するアルバムこれに対しては削除されません。
既定ではテーブルを削除すると参照リレーションシップに沿って反映されません。アルバムからアーティスト参照に関係 ArtistPlaysOnAlbum がある場合はアルバムを削除するアーティストの関連付けを削除せずアーティストを削除するアルバムは削除されません。
ただし削除は組み込みのリレーションシップに沿って反映されます。たとえばモデル要素が削除されるとダイアグラムの図形も削除されます。要素および図形はPresentationViewsSubject の参照のリレーションシップに関連付けられます。
ソースまたはターゲットのロールの要素に接続されているすべての関係は削除されます。対応するロールの要素のプロパティには削除された要素がありません。
伝達を設定するロールのオプションを削除します。
にから親ウィンドウへの参照の削除はリレーションシップに従ってまたは埋め込み子反映させることができます。
削除の伝達を設定するには
ユース ケース図で定義したに削除するロール を 選択します。ロールはドメイン リレーションシップ ボックスの左側によって表されます。
アルバムが削除されるたびにたとえばように指定する場合はドメイン クラス アーティストに接続するロールを選択するには関連のアーティストもおよび削除されます。
[プロパティ] ウィンドウで[入力] ENT0ENT プロパティを設定します。
F5 キーを押して次の点について確認してください :
このリレーションシップのインスタンスが削除されると選択したロールの要素も削除されます。
対応するロールの要素を削除した場合このリレーションシップのインスタンスが削除されこのロールに関連要素は削除されます。
ENT1ENT[出力] ウィンドウの [ENT0ENT] オプションを確認できます。ドメイン クラスユース ケースの詳細ペインのをクリックしボタンをクリックしてウィンドウに ENT0ENT [入力] ページを開きます。[入力] ENT1ENT オプションの各リレーションシップの一方のロールに示します。[入力] ENT2ENT オプションを既定の設定に関係なくなに別の効果がないかどうか ENT1ENT [出力] 列に示します。
プログラム コードを使用して削除の反映
DSL の定義ファイルのオプションが削除の数を即時に反映するかどうかを選択できるようにします。削除の反映より複雑な構成を実行するにはプログラム コードを記述できます。
[!メモ]
プログラムを追加するにはDSL を定義しDsl コード プロジェクトのコード ファイルを作成して生成されたコードのフォルダーのクラスを使用すると部分定義を作成します。詳細については、「ドメイン固有言語をカスタマイズするコードの記述」を参照してください。
削除するクロージャの定義
削除操作が削除される要素を最初に選択されているかを判断するためにクラス YourModelDeleteClosure を使用します。これは ShouldVisitRelationship() と ShouldVisitRolePlayer() を繰り返し呼び出しグラフ関係を示します。これらのメソッドをオーバーライドします。ShouldVisitRolePlayer はリンクのロールの 1 種類のリンクおよび要素 ID です。これは値のいずれか 1 つがを返す必要があります :
– VisitorFilterResult.Yes 要素が削除されDependency Walker は要素の他のリンクを試みることを開始してください。
– VisitorFilterResult.DoNotCare 削除することを別のクエリが応答しない要素は削除しないでください。
– VisitorFilterResult.Never 要素は別のクエリが Yes に一つの要素はそのほかのリンクを試みる必要ではありません。削除できないします。
// When a musician is deleted, delete their albums with a low rating.
// Override methods in <YourDsl>DeleteClosure in DomainModel.cs
partial class MusicLibDeleteClosure
{
public override VisitorFilterResult ShouldVisitRolePlayer
(ElementWalker walker, ModelElement sourceElement, ElementLink elementLink,
DomainRoleInfo targetDomainRole, ModelElement targetRolePlayer)
{
ArtistAppearsInAlbum link = elementLink as ArtistAppearsInAlbum;
if (link != null
&& targetDomainRole.RolePlayer.Id == Album.DomainClassId)
{
// Count other unvisited links to the Album of this link.
if (ArtistAppearsInAlbum.GetLinksToArtists(link.Album)
.Where(linkAlbumArtist =>
linkAlbumArtist != link &&
!walker.Visited(linkAlbumArtist))
.Count() == 0)
{
// Should delete this role player:
return VisitorFilterResult.Yes;
}
else
// Don’t delete unless another relationship deletes it:
return VisitorFilterResult.DoNotCare;
}
else
{
// Test for and respond to other relationships and roles here.
// Not the relationship or role we’re interested in.
return base.ShouldVisitRolePlayer(walker, sourceElement,
elementLink, targetDomainRole, targetRolePlayer);
}
}
}
クロージャの方法で削除を開始する前に削除される要素とリンクのセットを決定することになります。一つはモデルの他の部分ではとクロージャの結果をまとめて。
ただしテクニック削除子が関係グラフの隣にのみ影響することを前提としています : モデル内の他の部分の要素を削除するにはこのメソッドを使用できません。要素の追加または削除に応じて他の変更を加える場合は使用できません。
OnDeleting を使用してOnDeleted
ドメイン クラスまたはドメイン リレーションシップの OnDeleting() または OnDeleted() をオーバーライドできます。
OnDeleting は要素では削除されるとリレーションシップがドロップされる前に呼び出されます。そのほかの要素に対して一つでstore.ElementDirectory にあります。
複数の要素を同時に削除されるとOnDeleting は削除を実行する前にすべてのために呼び出されます。
IsDeleting は TRUE です。
OnDeleted は要素が削除されている呼び出されます。このメソッドは CLR ヒープに戻すが必要な場合は実行できますが他の要素で指定 store.ElementDirectory から削除されるようになります。リレーションシップの場合ロールロール プレーヤー古い参照します。IsDeleted は TRUE です。
ユーザーが要素を作成した後にを呼び出すと以前の削除がやり直すに繰り返される場合 OnDeleting と OnDeleted が呼び出されます。ストアの要素を更新するように this.Store.InUndoRedoOrRollback を使用します。詳細については、「方法: トランザクションを使用してモデルを更新する」を参照してください。
たとえば次のコードは最後の子が削除されると曲アルバムを削除します :
// Delete the parent Album when the last Song is deleted.
// Override methods in the embedding relationship between Album and Song:
partial class AlbumHasSongs
{
protected override void OnDeleted()
{
base.OnDeleted();
// Don't perform in-store actions in undo:
if (this.Store.InUndoRedoOrRollback) return;
// Relationship source and target still work:
// Don't bother if source is already on its way out:
if (!this.Album.IsDeleting && !this.Album.IsDeleted)
{
if (this.Album.Songs.Count == 0)
{
this.Album.Delete();
} } } }
要素が削除されるときにそのリレーションシップが削除されるときにの両方で動作するので通常リレーションシップの削除のロール トリガーは要素の方が便利です。ただし参照リレーションシップでは関連する要素が削除されますが自体リレーションシップが削除されると削除を反映したい場合があります。この例ではリレーションシップが削除されると最後の提供アーティストが削除されたときに応答しませんがアルバムを削除します :
using System.Linq; ...
// Assumes a many-many reference relationship
// between Artist and Album.
partial class Artist
{
protected override void OnDeleting()
{
base.OnDeleting();
if (this.Store.InUndoRedoOrRollback) return;
List<Album> toDelete = new List<Album>();
foreach (Album album in this.Albums)
{
if (album.Artists.Where(artist => !artist.IsDeleting)
.Count() == 0)
{
toDelete.Add(album);
}
}
foreach (Album album in toDelete)
{
album.Delete();
} } }
要素の Delete を実行するときOnDeleting と OnDeleted が呼び出されます。これらのメソッドは実際の削除との直前の後に発生したインライン。つまり常にです。コードが複数の要素を削除するとOnDeleting と OnDeleted はすべての置換が順番に呼び出されます。
削除規則およびイベント
OnDelete ハンドラーを使用する代わりに削除規則および削除のイベントを定義できます。
Deleting と Delete の規則はトランザクションだけであり元に戻すまたはやり直すに発生します。削除が実行されるトランザクションの最後に実行するキューに入れるで設定することもできます。規則を削除してキューにある削除した規則の前に常に実行されます。
リレーションシップ図の要素およびプロパティを含めるストアの要素は影響を与える変更を反映する規則を使用します。通常削除規則は削除を反映させる使用して置換の要素および関係を生成する削除規則が使用されます。
詳細については、「規則によって変更内容がモデル内に反映される」を参照してください。
Deleted ストアのイベントはトランザクションが開始され最後に戻す操作またはやり直し操作の後に呼び出されます。したがってVisual Studio ファイルデータベースのエントリまたはそのほかのオブジェクトのようなストアの外部のオブジェクトに削除を反映させるために使用できます。
詳細については、「イベント ハンドラーによって変更内容がモデル外に反映される」を参照してください。
注意 要素が削除されている場合はドメインのプロパティ値にアクセスできます関係のリンクを移動できません。ただしリレーションシップの削除されたイベントを設定した場合またはロール プレーヤーの 2 個の要素にアクセスできます。したがってモデル要素の削除に対するリンクされた要素にアクセスするにはモデル要素のドメイン クラスではなくリレーションシップの削除のイベントを設定します。
例の削除規則
[RuleOn(typeof(Album), FireTime = TimeToFire.TopLevelCommit)]
internal class AlbumDeletingRule : DeletingRule
{
public override void ElementDeleting(ElementDeletingEventArgs e)
{
base.ElementDeleting(e);
// ...perform tasks to propagate imminent deletion
}
}
[RuleOn(typeof(Album), FireTime = TimeToFire.TopLevelCommit)]
internal class AlbumDeletedRule : DeleteRule
{
public override void ElementDeleted(ElementDeletedEventArgs e)
{
base.ElementDeleted(e);
// ...perform tasks such as creating new elements
}
}
// The rule must be registered:
public partial class MusicLibDomainModel
{
protected override Type[] GetCustomDomainModelTypes()
{
List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
types.Add(typeof(AlbumDeletingRule));
types.Add(typeof(AlbumDeletedRule));
// If you add more rules, list them here.
return types.ToArray();
}
}
例で行うイベント
partial class NestedShapesSampleDocData
{
protected override void OnDocumentLoaded(EventArgs e)
{
base.OnDocumentLoaded(e);
DomainRelationshipInfo commentRelationship =
this.Store.DomainDataDirectory
.FindDomainRelationship(typeof(CommentsReferenceComponents));
this.Store.EventManagerDirectory.ElementDeleted.Add(commentRelationship,
new EventHandler<ElementDeletedEventArgs>(CommentLinkDeleted));
}
private void CommentLinkDeleted (object sender, ElementDeletedEventArgs e)
{
CommentsReferenceComponents link = e.ModelElement as CommentsReferenceComponents;
Comment comment = link.Comment;
Component component = link.Subject;
if (comment.IsDeleted)
{
// The link was deleted because the comment was deleted.
System.Windows.Forms.MessageBox.Show("Removed comment on " + component.Name);
}
else
{
// It was just the link that was deleted - the comment itself remains.
System.Windows.Forms.MessageBox.Show("Removed comment link to "
+ component.Name);
}
}
}
UnMerge
親は子要素をアタッチする操作は マージと 呼ばれます。この要素は要素の新しい要素または要素グループをツールボックスから作成されたかまたはモデルの他の部分から移動するかクリップボードからコピーされたときに発生します。新しい親と子の間に埋め込むリレーションシップの作成と同様マージ操作では追加の関係を設定する要素のサブ要素と設定のプロパティの値を作成します。マージ操作は要素のマージのディレクティブ (EMD) にカプセル化されます。
EMD はMergeDisconnect を補足する unmerge または操作をカプセル化します。マージを使用して構築された要素のクラスターがある場合は一貫した状態残りの要素を保持するにはから要素を削除するには関連する unmerge を使用することをお勧めします。unmerge 操作は前のセクションで説明した手法を使用します。
詳細については、「要素作成処理および要素移動処理のカスタマイズ」を参照してください。