標籤:
ABP學習經驗
- 1. 視圖中(控制器中直接使用倉儲)會遇到使用實體外鍵,出現資料庫連接關閉的錯誤
初學者經常會犯這樣一個錯誤,沒錯說的就是我自己,這個問題折騰了我很長世間。還是沒有細看文檔,對abp領會不深。
開始描述問題,一開始我想著方便,因為只是一個簡單的表對象輸出,該表的entity每個欄位都會別輸出到視圖,所以我想每筆要搞那麼麻煩,再去建立一個Dto類,結果我在視圖中嘗試擷取一個entity的外鍵對象時,出錯了,錯誤的描述就不粘上來了,大意是資料庫上下文已被登出,所以不能通過它取資料拿資料。
出現這個錯誤的原因很簡單:
比如User類型引用Role類型。當你從資料庫擷取User時,Role屬性並沒有被填充。當你第一次讀取Role屬性時,才會從資料庫中載入Role。所以,當你返回這樣一個實體給展現層時,很容易引起副作用(從資料庫中載入),而abp架構被設計為一旦service或者控制器中的action執行完畢就會自動關掉當前的資料庫連接。
所以建議:
在展現層中使用實體還會有更多的問題。最佳的方案就是展現層不應該引用任何包含領域層的程式集。
- 2. Abp的多租戶過濾的問題
用abp做的第一個公司項目,就是多租戶的一個OA管理系統,之前公司一直用mvc,突然要換架構,老闆讓我帶頭開始搞這個新項目,沒辦法,只好硬著頭皮上。一開始很多地方搞不定,所以這些地方還是拋棄了abp的原有設計,導致這個架構用得有些不倫不類的,沒辦法,時間太緊。
其中,多租戶就是一個比較坑的地方。原本就是比較中意abp自動實現多租戶過濾這套基礎設施的,於是花了大力氣做了改寫了一套通過資料表產生entity和dbcontext的模板,讓產生的entity會根據資料表是否包含tenantid自動繼承IMayHaveTenant介面。 但是,和設計資料庫的同事沒溝通好,設計的資料表全都關聯了另一個代表多租戶的資料表的主鍵,這是其中的坑之一,也就是除了使用者表擁有tenantid其他表都沒有。 然後,當然abp多租戶自動過濾功能自然有了,但是遇到一個比較悲催的問題,使用者登入的時候,多租戶依然會去進行過濾,這就導致使用者一旦登出登陸狀態後,就無法登陸了,(我的abpsession擷取tenantid是從cookie中擷取的),登出後tenantid是空的,查詢所有使用者會自動過濾所有tenantid非空的使用者,導致擷取不了使用者很蛋疼,當時還不知道怎麼動態禁用資料自動過濾系統,所以就是用了模組啟動時全域禁用多租戶,在那個PreInitialize方法中設定,但是無效。所以只好去掉了使用者entity繼承IMayHaveTenant介面,但是問題還沒完,由於項目的也無原因,必須在登陸時不存在資料庫的使用者進行直接註冊,所以需要為新登陸的使用者賦予tenantid,然而由於當前的cookie中tenantid為空白,多租戶機制依然還在起作用,導致不能給一個實體賦予不同於當前tenantid值。扯了這麼多,只是想描述和記錄下當時踩坑過程,說實話由於abp的相關資料確實很少,網上基本上都找不到有關問題的直接解答,所以很走了一些彎路。細看了一些文檔後,終於發現如何優雅的解決上面的這個問題:
using(_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.SoftDelete)){
varpeople2 = _personRepository.GetAllList();
}
這個是禁用虛刪除的資料過濾,禁用多租戶的應該也是可以以此種方式實現的,具體的代碼文檔沒有,需要的自己點一下應該是能很輕易找到的。
Abp問題解決集合1