在我這個系列中,我主要以我正在開發的雲會員管理系統為例進行介紹Web API的應用,由於雲會員的數據設計是支持多個商家公司,而每個公司又可以包含多個店鋪的,因此一些字典型的數據需要考慮這方面的不同。如對於證件類型,收費處理狀態,民族,職稱等這些固定化的內容,我們可以放到全局字典里面,但是對於一些如會員相關的字典數據,如產品單位、產品類型等內容,如果也全部規定為全局的系統字典,那么就缺乏靈活性,這些數據應該可以由各自進行差異化處理。
1、雲會員系統的字典數據模型
我們先來了解下基於Web API接口的雲會員管理系統的總體界面效果。
由於一般的雲會員系統,都是允許用戶注冊一個公司,然后公司層面開設多個商鋪的,如系統的登陸界面如下所示。
因此數據的范圍需要考慮的更廣,他們的關系如下所示。
而我們原先設計的字典模型如下所示。
而在公司數據這個層次上,我們需要考慮公司層級的數據字典存儲,但是我們進一步分析可以看到,雖然數據字典數據是公司層級的,但是數據字典的類型(如證件類型、產品類型等)這些是固定不變的,也就是我們如果存儲公司層級的字典數據,那么也只是需要存儲對應的字典項目即可。因此我們可以增加多一個和TB_DictData的數據表類似的表進行存儲即可,它的數據設計如下所示。
為了方便在系統里面使用同一的字典項目內容,我們創建一了一個統一的字典項目管理模塊,也就是系統字典管理界面,如下所示。
2、公司層級的字典數據存儲實現
有了上面的設計模型,相信大多數人員都可以想到它的具體實現思路了。
首先我們需要以系統字典數據為參考,如默認就是取系統的字典項目數據,如果公司級別的用戶修改或者刪除了字典數據內容,那么對應的字典類別的字典項目就應該以修改的為准了。
但是我們不可能為新建公司賬戶的時候,都為每個公司自動創建一份對應類型的字典數據,那樣稍顯麻煩,而且一開始就創建也比較麻煩。
先建立一個公司字典的數據管理界面,它和字典數據管理界面一樣,不過是存儲在另外一個表里面,自動根據當前用戶的公司標識進行存儲的。
批量添加公司字典的數據如下所示。
一般我們在使用公司層級的字典數據或者系統公共層級的字典數據的時候,都是根據字典類型進行判斷的。
因此在公司層級根據字典項目類型獲取數據的時候,我們在業務接口底層做了判斷,判斷如果對應公司的字典項沒有數據,則復制一份過去,如果公司層次有對應的數據類型,那么就獲取公司層級的字典項目數據即可。
具體的代碼邏輯如下所示。
/// <summary> /// 根據字典類型名稱獲取所有該類型的字典列表集合 /// </summary> /// <param name="dictType">字典類型名稱</param> /// <param name="corpId">公司ID</param> /// <returns></returns> public List<CorpDictDataInfo> FindByDictType(string dictTypeName, string corpId) { ICorpDictData dal = baseDal as ICorpDictData; List<CorpDictDataInfo> list = dal.FindByDictType(dictTypeName, corpId); //如果公司字典沒有數據,則從系統字典獲取 if (list.Count == 0) { List<DictDataInfo> dict = BLLFactory<DictData>.Instance.FindByDictType(dictTypeName); foreach (DictDataInfo info in dict) { list.Add(new CorpDictDataInfo(info, corpId)); } //寫入公司字典表,避免下次再去獲取 foreach (CorpDictDataInfo info in list) { baseDal.Insert(info); } } return list; }
在Web API的控制器接口,還是和其他的處理一樣,增加對應的參數處理即可。
/// <summary> /// 根據字典類型名稱獲取所有該類型的字典列表集合 /// </summary> /// <param name="dictType">字典類型名稱</param> /// <param name="corpId">公司ID</param> /// <returns></returns> [HttpGet] public List<CorpDictDataInfo> FindByDictType(string dictTypeName, string corpId, string token) { //令牌檢查,不通過則拋出異常 CheckResult checkResult = CheckToken(token); return BLLFactory<CorpDictData>.Instance.FindByDictType(dictTypeName, corpId); }
在Facade層定義字典的對應接口的時候,我們的代碼如下所示
/// <summary> /// 根據字典類型名稱獲取所有該類型的字典列表集合 /// </summary> /// <param name="dictType">字典類型名稱</param> /// <param name="corpId">公司ID</param> /// <returns></returns> [OperationContract] List<CorpDictDataInfo> FindByDictType(string dictTypeName, string corpId);
在基於Web API的封裝調用接口,我們的調用封裝類如下所示。其中token以及Web API的相關參數處理,在基類模塊進行了封裝,減少了很多代碼的拼接。
/// </summary> /// <param name="dictType">字典類型名稱</param> /// <param name="corpId">公司ID</param> /// <returns></returns> public List<CorpDictDataInfo> FindByDictType(string dictTypeName, string corpId) { var action = "FindByDictType"; string url = GetTokenUrl(action) + string.Format("&dictTypeName={0}&corpId={1}", dictTypeName, corpId); List<CorpDictDataInfo> result = JsonHelper<List<CorpDictDataInfo>>.ConvertJson(url); return result; }
然后我們在界面上的字典項目下拉列表,則可以通過擴展函數的方式進行綁定。
/// <summary> /// 初始化字典列表內容 /// </summary> private void InitDictItem() { //初始化代碼 this.txtProductType.BindDictItemsByCorp("會員產品類型", LoginUserInfo.CompanyId); }
/// <summary> /// 綁定下拉列表控件為指定的數據字典列表[如果公司字典記錄不存在,則使用系統字典記錄,否則使用公司記錄] /// </summary> /// <param name="combo">下拉列表控件</param> /// <param name="dictTypeName">數據字典類型名稱</param> public static void BindDictItemsByCorp(this ComboBoxEdit combo, string dictTypeName, string corpId) { BindDictItemsByCorp(combo, dictTypeName, corpId, null); } /// <summary> /// 綁定下拉列表控件為指定的數據字典列表[如果公司字典記錄不存在,則使用系統字典記錄,否則使用公司記錄] /// </summary> /// <param name="combo">下拉列表控件</param> /// <param name="dictTypeName">數據字典類型名稱</param> /// <param name="defaultValue">控件默認值</param> public static void BindDictItemsByCorp(this ComboBoxEdit combo, string dictTypeName, string corpId, string defaultValue) { Dictionary<string, string> dict = CallerFactory<ICorpDictDataService>.Instance.GetDictByDictType(dictTypeName, corpId); List<CListItem> itemList = new List<CListItem>(); foreach (string key in dict.Keys) { itemList.Add(new CListItem(key, dict[key])); } BindDictItems(combo, itemList, defaultValue); }
以上就是一個整體性的思路,並在系統中能夠順利解決問題的做法,希望大家可以借鑒。
系列文章如下所示:
Web API應用架構在Winform混合框架中的應用(1)
Web API應用架構在Winform混合框架中的應用(2)--自定義異常結果的處理
Web API應用架構在Winform混合框架中的應用(3)--Winfrom界面調用WebAPI的過程分解
Web API應用架構在Winform混合框架中的應用(4)--利用代碼生成工具快速開發整套應用
Web API應用架構在Winform混合框架中的應用(5)--系統級別字典和公司級別字典並存的處理方式