
Rafy 框架又添新成員:幽靈插件。本文將解釋該插件的場景、使用方法、原理。
場景
在開發各類數據庫應用系統時,往往需要在刪除數據時不是真正地刪除數據,而只是把數據標識為‘已刪除’狀態。這些數據在業務邏輯上是已經完全刪除、不可用的數據,但是不能在數據庫中真正的把它們刪除,而是需要永久保留這些歷史數據。即開發人員常說的‘假刪除’功能。
這種需求往往是系統級的。往往不是針對某一張表,而很可能是針對系統中的所有表都需要實現‘假刪除’功能。
使用方法
由於這種需求比較常見,所以我們決定專門為該功能寫一個獨立的 Rafy 插件。這樣,開發人員需要實現假刪除功能時,只需要引用該插件后,系統中所有刪除的實體都自動變為‘幽靈’,同時這些幽靈數據在倉庫的所有查詢中都將被自動過濾。
使用步驟:
- 通過 Nuget Package Manager 搜索並安裝 Rafy.Domain.EntityPhantom 插件。
- 在 DomainApp 中添加該插件:
class JXCApp : DomainApp { protected override void InitEnvironment() { //添加幽靈插件到 Rafy 應用程序集中。 RafyEnvironment.DomainPlugins.Add(new Rafy.Domain.EntityPhantom.EntityPhantomPlugin()); RafyEnvironment.DomainPlugins.Add(new JXCPlugin()); base.InitEnvironment(); } }
- 為需要幽靈功能的實體打開該功能,需要在實體元數據配置中進行配置:
internal class UserConfig : JXCEntityConfig<User> { protected override void ConfigMeta() { Meta.MapTable().MapAllProperties(); //在實體配置中加入此行代碼,為實體啟用幽靈功能。 Meta.EnablePhantoms(); } }
效果
所有繼承自 Entity 的實體都會統一的添加一個 IsPhantom 的屬性。這個屬性表示這個實體是否為‘幽靈’,即已經刪除的數據。
- 開發者可以使用 Meta.EnablePhantoms() 來為某個指定的實體類型開啟‘幽靈’功能。
- 開啟該功能的實體的 IsPhantom 屬性會自動映射到數據庫中。
- 在保存實體時,如果要刪除一個聚合實體,則這個聚合中的所有實體都將會被標記為‘幽靈’狀態。
- 在查詢實體時,所有的查詢,都將會自動過濾掉所有‘幽靈’狀態的數據。(手寫 SQL 查詢的場景不在考慮范圍內。)
- 使用批量導入數據插件進行數據的批量導入時,批量刪除的實體同樣都會被標記為‘幽靈’狀態。
運行程序后,數據庫中的字段,已經自動添加上 IsPhantom 字段了:
在使用 GetAll 查詢所有實體時,框架自動加上一 IsPhantom = false 的過濾條件:
SELECT * FROM [User] WHERE [User].[IsPhantom] = @p0 ORDER BY [User].[Id] ASC Parameters:False
數據的刪除,變為更新表中對應行的 IsPhantom 字段為 True:
UPDATE [User] SET [Name] = @p0,[IsPhantom] = @p1 WHERE [Id] = @p2 Parameters:"Name",True,3
原理
幽靈插件的原理比較簡單。在 Rafy 框架的基礎上,以插件的形式對 Rafy 框架中實體的數據層進行了擴展。在啟用實體的幽靈功能后,該實體的 DataProvider 類型的 Deleting、Querying 事件都會被監聽並擴展:
/// <summary> /// 數據的刪除、查詢的攔截器。 /// </summary> internal static class PhantomDataInterceptor { internal static void Intercept() { RepositoryDataProvider.Deleting += RepositoryDataProvider_Deleting; RepositoryDataProvider.Querying += RepositoryDataProvider_Querying; } }
在查詢時,框架自動分析出當前查詢的 SQL 樹,並在主查詢上加上 IsPhantom = false 的過濾條件。
有興趣的同學,可以查看 Rafy 框架源碼。![]()
PS:該文已經納入《 Rafy 用戶手冊》中。

