自訂刪除行為
刪除項目通常會使相關的項目,也一併刪除。 所有關聯性連接到它,而且也會刪除任何子項目。 這種行為名為刪除傳播。 您可以自訂刪除傳用,例如若要排列其他相關的項目會被刪除。 藉由撰寫程式碼,您可刪除傳用模型的狀態而定。 您也可以讓其他的變更就會發生一項刪除作業回應。
本主題包含下列章節:
預設的刪除行為
設定角色的傳播刪除選項
覆寫該刪除終止 – 使用這項技術,刪除動作可能會導致無法刪除相鄰的項目。
使用 OnDeleting 和 OnDeleted – 使用這些方法的回應無法在其中包含其他的動作,例如更新值之內或之外的存放區。
刪除規則 – 使用規則來傳播更新任何的保證,其中一項變更可能會導致其他人的存放區內。
刪除事件 – 使用外部存放區中,例如至其他的更新傳播的儲存區事件Visual Studio的文件。
UnMerge – 使用 UnMerge 操作來復原合併作業,連接至其父代的子項目。
預設的刪除行為
根據預設,下列規則會控制刪除傳播:
如果刪除的項目時,也會一併刪除所有內嵌項目。 內嵌的這個項目做為來源的關聯性的目標就是內嵌的項目。 比方說,歌曲到專輯內嵌關係時,然後刪除特定的相簿後,其所有的歌曲會也被刪除。
相反地,刪除歌曲並不會刪除相簿。
預設情況下,刪除動作不會散佈沿著參考關聯性。 如果有參考關係到演出者專輯從 ArtistPlaysOnAlbum,刪除相簿並不會刪除任何相關的演出者,並刪除演出者並不會刪除任何的專輯。
不過,刪除動作不會傳播以及一些內建的關聯。 比方說,當刪除模型元素時,也會刪除它在圖表上的圖形。 項目] 圖形則與相關聯的PresentationViewsSubject參考關聯性。
已連線到的項目,或是在 「 來源 」 或 「 目標 」 角色中,每個關聯性會被刪除。 角色屬性相反角色處的項目不會再包含已刪除的項目。
設定角色的傳播刪除選項
您可能會導致傳播沿著參考關聯性,或從內嵌的子系至其父代的刪除動作。
若要設定刪除傳播
在 DSL 定義圖表中,選取 [ 角色到您想要刪除的傳播。 角色都會列在左邊或右邊網域的關聯性] 方塊中。
比方說,如果您想要指定每當刪除相簿時,相關的演出者會一併刪除,然後選取 [連線到網域類別演出者的角色。
在 [屬性] 視窗中,設定傳播刪除屬性。
按 F5 並確認:
刪除此關聯性的執行個體時,在所選角色的項目也會被刪除。
刪除位於相反角色的項目時,此關聯性的執行個體都會被刪除,,並在這個角色的相關項目將被刪除。
您也可以查看傳播刪除 選項在 DSL 詳細資料視窗。 選取網域類別,並在 DSL 細節] 視窗中,開啟刪除行為以按一下按鈕,在視窗的顯示畫面。 傳播針對每個關聯性的相反角色的選項都會顯示出來。 刪除樣式 ] 欄位會指示是否 傳播選項的預設值,但它並沒有任何不同的效果。
使用程式碼來刪除傳播
DSL 定義檔中的選項僅可讓您選擇是否刪除將傳播到即時的鄰居。 若要實作更複雜的配置,刪除傳用的您可以撰寫程式碼。
![]() |
---|
若要將程式碼新增至您的 DSL 定義,建立一個不同的程式碼檔案中Dsl專案,並撰寫來擴充產生的程式碼資料夾中的類別的部分定義。如需詳細資訊,請參閱 撰寫程式碼來自訂網域指定的語言。 |
定義刪除終止
刪除作業中使用類別 YourModelDeleteClosure來決定要刪除時,提供初始的選取範圍的項目。 它會呼叫ShouldVisitRelationship()和ShouldVisitRolePlayer()重複,逐步讀取關聯性的圖形。 您可以覆寫這些方法。 ShouldVisitRolePlayer 隨附的連結,並在其中一個連結的角色的項目識別。 它應該傳回下列值之一:
VisitorFilterResult.Yes– 項目應被刪除,而且查核器應該繼續重試此項目中的其他連結。
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 is true.
使用者叫用建立的項目後的復原和取消復原中有重複的較早的刪除時,會呼叫 OnDeleting 和 OnDeleted。 使用this.Store.InUndoRedoOrRollback來避免去更新儲存在這些情況下的項目。 如需詳細資訊,請參閱 HOW TO:使用交易更新模型。
例如,下列程式碼會刪除相簿刪除它的最後一個子系歌曲時:
// 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。
如需詳細資訊,請參閱 事件處理常式傳播模型外的變更。
警告
當項目已遭刪除時,您可以存取其網域屬性值,但您不能瀏覽關聯性連結。不過,如果您設定關聯性已刪除的事件,您也可以存取其角色扮演者兩個項目。因此,如果您想要刪除的模型項目來回應,但要存取它所連結的項目,將 delete 事件之間的關係而不是模型項目的網域類別。
刪除規則範例
[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);
}
}
}
取消合併儲存格
將子項目附加至其父代的作業稱為合併。 這會發生在新的項目,或從工具箱] 中,建立或從另一個組件的模型中,移動或從 [剪貼簿] 複製的項目群組。 除了建立內嵌的關聯性父代和新的子系之間,合併作業也可以設定其他的關聯、 建立輔助的項目,及設定屬性值的項目中。 合併作業會封裝中的項目合併指示詞 (EMD)。
EMD 也會封裝互補取消合併儲存格或MergeDisconnect作業。 如果您有一群項目已建構成使用合併列印時,最好是使用相關聯取消合併儲存格來移除項目,如果您想要保留剩餘的項目處於一致的狀態。 Unmerge 作業通常會使用前一章節所述的技巧。
如需詳細資訊,請參閱 自訂項目的建立和移動。