使用過CSLA的朋友們應該知道“命令對象”這個概念,它可以以多種方式使用,可以直接被使用者介面代碼所調用,以執行應用伺服器上的任意代碼,但更多的是被用在其他業務對象裡面,以執行應用程式伺服器上的代碼。
最近在寫命令對象的時候,遇到個問題不太好解決,所以想把思路寫出來,讓大家給分析下。問題描述:要求在瀏覽介面刪除資料,而瀏覽介面只是為了讓使用者看到一些基本的資訊,只做展示而已,所以用的是唯讀對象,這時如果要做刪除就只能通過命令對象來做,可是每一個對象的刪除操作都得寫一個命令對象,而它們之間的差異也就是對象不同而已,所以想把這個不同提取出來作為條件傳進去以簡化代碼,例如刪除文章和廣告這兩個對象的命令對象代碼如下:
[Serializable] public class cmdDeleteArticle : Csla.CommandBase { private List<string> _uniqueIds; private cmdDeleteArticle() { } private cmdDeleteArticle(List<string> uniqueIDs) { _uniqueIds = uniqueIDs; } #region Factory Methods public static void DeleteArticle(List<string> uniqueIDs) { var cmd = new cmdDeleteArticle(uniqueIDs); cmd = DataPortal.Execute<cmdDeleteArticle>(cmd); } #endregion //Factory Methods #region Data Access protected override void DataPortal_Execute() { using (var mgr = ContextManager<EasyBridge.DataAccess.ebSynDataContext> .GetManager(EasyBridge.DataAccess.Database.EasyBridgeSyn)) { foreach (string uniqueId in _uniqueIds) { try { var article = mgr.DataContext.Articles.SingleOrDefault(p => p.UniqueID == uniqueId); if (article != null) { mgr.DataContext.Articles.DeleteOnSubmit(article); } mgr.DataContext.SubmitChanges(); } catch (Exception ex) { throw new Exception(ex.Message); } } } } #endregion //Data Access }
[Serializable] public class cmdDeleteAdvert : Csla.CommandBase { private List<string> _uniqueIds; private cmdDeleteAdvert() { } private cmdDeleteAdvert(List<string> uniqueIDs) { _uniqueIds = uniqueIDs; } #region Factory Methods public static void DeleteAdvert(List<string> uniqueIDs) { var cmd = new cmdDeleteAdvert(uniqueIDs); cmd = DataPortal.Execute<cmdDeleteAdvert>(cmd); } #endregion //Factory Methods #region Data Access protected override void DataPortal_Execute() { using (var mgr = ContextManager<EasyBridge.DataAccess.ebSynDataContext> .GetManager(EasyBridge.DataAccess.Database.EasyBridgeSyn)) { foreach (string uniqueId in _uniqueIds) { try { var advert = mgr.DataContext.Adverts.SingleOrDefault(p => p.UniqueID == uniqueId); if (advert != null) { mgr.DataContext.Adverts.DeleteOnSubmit(advert); } mgr.DataContext.SubmitChanges(); } catch (Exception ex) { throw new Exception(ex.Message); } } } } #endregion //Data Access }
可以看出,代碼中除了資料內容的表不同並無其他差異:因此,我想構造一個基類,簡單封裝一下這個變化。基類構造如下:
[Serializable] public class cmdDeleteBase<T> : Csla.CommandBase where T : Type { private List<string> _uniqueIDs; private System.Data.Linq.Table<T> _tables; private cmdDeleteBase() { } private cmdDeleteBase(List<string> uniqueIDs, System.Data.Linq.Table<T> tables) { _uniqueIDs = uniqueIDs; _tables = tables; } #region Factory Methods public virtual static void DeleteRecord(List<string> uniqueIDs, System.Data.Linq.Table<T> tables) { var cmd = new cmdDeleteBase<T>(uniqueIDs, tables); cmd = DataPortal.Execute<cmdDeleteBase<T>>(cmd); } #endregion #region Data Access protected override void DataPortal_Execute() { using (var mgr = ContextManager<EasyBridge.DataAccess.ebSynDataContext> .GetManager(EasyBridge.DataAccess.Database.EasyBridgeSyn)) { foreach (string uniqueID in _uniqueIDs) { try { var businessObject = mgr.DataContext.GetTable<T>().SingleOrDefault(p => p.UniqueID == uniqueID); if (businessObject != null) { mgr.DataContext.GetTable<T>().DeleteOnSubmit(businessObject); } mgr.DataContext.SubmitChanges(); } catch (Exception ex) { throw new Exception(ex.Message); } } } } #endregion //Data Access }
現在有幾個問題:
1. 用泛型的話,那個Type沒法確定,因為LINQ2SQL產生的類沒有基類
[Table(Name="dbo.Article")]
public partial class Article : INotifyPropertyChanging, INotifyPropertyChanged
2. T 確定不了 那個 p => p.UniqueID == uniqueID 就推斷出來