王建祥,王洪澤
(河南省濟源鋼鐵(集團)有限公司 信息化儀表處, 河南 濟源 454650)
隨著信息化技術的發展,管理信息系統得到普遍應用,而權限管理系統是各類管理信息系統的前提和基礎。本文權限管理系統的設計按EF模型生成數據庫、各層深度解耦、設計T4模板自動生成代碼、設計前端等步驟進行[1-2]。
根據ASP.Net MVC系統的特性,權限管理系統的設計目標是:
1.UserInfo---RoleInfo---ActionInfo;用戶擁有角色,權限擁有角色,從而用戶擁有權限。
2.UserInfo---R_UserInfo_ActionInfo;用戶直接擁有特殊權限。
具體實現過程如圖1所示。

圖1 權限管理的目標
本系統使用Visual Studio 2019 Enterprise 16.11版本軟件進行權限管理軟件開發和調試,使用ASP.NET MVC技術進行設計,其中DAL層到BLL層的解耦使用復雜工廠技術,BLL層到UI層的解耦使用Spring.Net技術[3]。
2.1.1 建立方案并組織管理各層項目
新建解決方案文件夾: 解決方案文件夾是虛擬文件夾,其作用是便于項目的管理。

表現層——項目類型w e b 應用程序---.N E T Framework
jygt.AutoWeightSystem.UI.Portal
2.1.2 Model 層添加實體數據模型并生成數據庫
使用EF技術的Model First方式生成數據庫: 項目開始沒有數據庫,根據EF設計模型,進行模型同步完成數據庫及表的創建。
添加ADO.NET實體數據模型---空EF設計器,命名DataModel
1、在EF設計器DataModel中添加實體及屬性、關聯
(1) 添加實體模型UserInfo
(2) 添加實體模型OrderInfo
(3) 建立實體UserInfo與實體OrderInfo兩個實體之間1對多的關聯。
2、根據模型生成數據庫
右擊EF設計器空白處---添加代碼生成項,把名稱改成DataModel.tt,即生成上述實體模型UserInfo、實體模型OrderInfo對應的實體類文件。
右擊EF設計器空白處---根據模型生成數據庫,生成DataModel.edmx.sql文件,執行DataModel.edmx.sql文件生成數據庫及表。EF技術生成的數據庫如圖2所示。

圖2 EF 技術生成的數據庫
2.1.2 設計DAL 數據訪問層
查詢方法的設計思路:
1.方法選擇。方法需能接受用戶輸入的任意條件,返回值應是b o o l 類型,因此可以用委托Func
2.方法返回值類型選擇。返回值是用戶,由于返回的用戶個數不確定,不能用UserInfo類型,可使用List
3.繼續深入考慮,如果返回值是List
繼續深入思考方法,F u n c
綜上,DAL層使用如下方法實現查詢:

2.1.3 設計封裝數據訪問層基類BaseDAL
DAL層的各個方法,經測試全部正確后,目前只是針對UserInfoDAL,針對OrderInfoDAL同樣也有增刪改查等類似方法,僅數據實體對象不同,還有其他實體都要寫類似的增刪改查方法,不經專門處理就會有很多重復工作。因此把相同的方法提出來,封裝成一個基類,所有類似通用方法寫在此基類里面,然后讓子類去繼承使用該基類的增刪改查方法。
需要使用泛型類,即把BaseDAL類改成泛型類,然后加上泛型約束,
public class BaseDAL

2.1.4 添加數據訪問層的接口IDAL
在數據訪問層建立的基礎上,創建業務邏輯層(BLL)類庫。在jygt.AutoWeightSystem.BLL層中新建一個類UserInfoBLL,然后添加方法,

上述做法需要改進的地方:
1.上述做法會使jygt.AutoWeightSystem.BLL層與jygt.AutoWeightSystem.EFDAL層緊密耦合在一起,EFDAL層發生變化BLL層就必須跟著變,比如UserInfoDAL的名稱變了,BLL層必須跟著變。
2.DAL層的可能變化點:(1)跨數據庫,如SqlServer、Oracle、 mysql,對于采用EF技術,本身就支持跨數據庫(2)數據庫訪問驅動層驅動變化,比如不采用EFDAL,采用ADODAL或者NHDAL。
3.項目設計原則:模塊內高內聚,模塊間低耦合。期望DAL層變化的情況下,BLL層不需要變化或者變化最小。
于是進行如下改進:
D A L 層中就添加一個類庫項目j y g t .AutoWeightSystem.IDAL(注意命名規范),表示DAL層的接口,創建IuserInfoDAL接口。

然后在IuserInfoDAL接口里定義抽象的增刪改查的方法。同理,添加OrderInfoDAL等實體的DAL接口IOrderInfoDAL,里面同樣添加抽象的增刪改查方法。這時由IuserInfoDAL接口和IOrderInfoDAL接口可以抽象出一個基類接口。
2.1.5 抽象出數據訪問層的基類接口
p u blic interf ace IBaseD A L

接著讓IUserInfoDAL、IOrderInfaDAL繼承IBaseDAL,原有的方法結構注釋或刪除,IorderInfaDAL類不存在就新建,并導入Model命名空間。然后修改EFDAL層下的UserInfoDAL和OrderInfoDAL,讓其分別實現IUserInfoDAL、IOrderInfaDAL,同時添加對IDAL層jygt.AutoWeightSystem. IDAL的引用。這樣UserInfoDAL實例用接口IUserInfoDAL來接收,使用接口接收就可以做到不依賴具體實現。
2.1.6 用接口隔離業務邏輯層BLL 對DAL 的依賴
切換到業務邏輯層UserInfoBLL,用接口類型來接收new UserInfoDAL(),這個前提是UserInfoDAL類要實現IUserInfoDAL接口,否則不能接收,其好處是下面的方法依賴的是接口,因為接口中的成員都是抽象的,具體實現發生變化不影響接口。如此new UserInfoDAL()即數據訪問驅動層采用其他技術來實現對數據庫的訪問,下面的方法代碼不發生變化。UserInfoDAL();//具體實現方法;

例如,數據訪問驅動層改用Nhibernate實現對數據庫的訪問。實現方法如下。
添加類庫項目,命名為jygt.AutoWeightSystem.NHDAL,在該類庫項目下添加NHUserInfoDAL類,讓其去實現IUserInfoDAL接口。
2.1.7 通過簡單工廠進一步隔離BLL 層對DAL 的依賴
在DAL層下新建類庫項目jygt.AutoWeightSystem.DALFactory,下面新建靜態的StaticDALFactory類,類下面創建GetUserInfoDAL方法,因為下面new UserInfoDAL()、new NhUserInfoDAL等都可以接受,即能接受下面的變化。
即由:

簡單工廠的優勢在于,如果數據訪問驅動層的實現技術發生改變,只需更改簡單工廠中的return new UserInfoDAL(),而BLL層程序不需要做修改。如果程序已經發布,只需要把簡單工廠的程序集重新生成后,把服務器上的相應的程序集替換即可,BLL層代碼等不做改動。
2.1.8 通過抽象工廠實現BLL 層與DAL 層徹底解耦
至此,通過簡單工廠使業務邏輯層與數據訪問層已經解耦,即通過簡單工廠隔離了BLL層對DAL層的依賴。但是依然需要修改程序,即通過修改配置文件其他程序不做修改,不通過new實例化對象。這時要實現BLL層與DAL層徹底解耦,可使用抽象工廠的反射方式來實現。要使用反射就要使用當前程序集。
數據訪問驅動層的不同實現方法其實就是程序集名稱不同,前提是不同數據訪問驅動層封裝同一個實體的DAL名稱相同,比如都為UserInfoDAL,不要一個是UserInfoDAL,另一個是NhUserInfoDAL,所以這里把jygt.AutoWeightSystem.NHDAL層下的NhUserInfoDAL重命名為UserInfoDAL與jygt.AutoWeightSystem.EFDAL下的名稱相同,這就是約定大于配置的思想。
以后如果實現數據訪問驅動層的技術改變,只要修改配置文件web.Config中的

2.1.9 保證線程內共享一個上下文實例
數據訪問層BaseDAL中上下文實例通過new方法產生,語句如下:

只要執行這句代碼就會產生一個上下文實例,不能保證線程內共享一個上下文實例。
這時也需要把new方法去掉,不通過new 來實例化出一個上下文對象。也可以用一個單獨類來產生上下文實例,由于本項目DAL主要用EF來實現,所以在jygt.AutoWeightSystem.E F D A L 層下單獨再新建一個D b C o n te n t F a c t o r y類,專門用來保證線程內共享一個上下文實例。

由于使用DbContext作為返回值類型,Model層中如果還有其他的上下文對象,只要把new 后面的具體上下文對象名稱做對應修改就可以實現切換上下文對象。
然后在BaseDAL中的

2.1.10 封裝數據訪問層的統一入口DbSession 類
封裝DBSession類,讓其擁有所有DAL的實例(或者說是用來生成DAL實例對象的類/工廠)和更新到數據庫的方法,也即是讓DBSession類封裝成整個數據訪問層與數據庫的會話類,像EF上下文封裝了所有表對應實體集合DbSet
接下來把BaseDAL.cs中所有DB.SaveChanges()代碼全部刪除或注釋掉,即不在數據訪問層使每一操作都與數據庫交互。
優勢:數據提交的權利從數據庫訪問層提到了業務邏輯層。批量操作可以一次性提交到數據庫,如果在數據庫訪問層每個方法都有SaveChanges()方法,那么每操作一次都會與數據庫發生交互。而到了業務層來了就非常靈活,可以批量操作后一起提交,需要時也可以一個操作結束就提交,只需加上DBSession.SaveChanges();即可。
2.1.11 建立IDBSession 接口,讓業務層依賴接口
建立IDBSession接口,讓業務層依賴接口,保證一次請求共用一個dbsession實例
上面業務邏輯層中有語句:DBSession dbsession =new DBSession();
即DBSession所在層與BLL層之間緊密依賴。項目一般要求層與層之間的調用最好通過接口隔離,不要依賴于具體實現,即使這個接口沒有其他意義。
因此再定義一個IDBSession,用來隔離DBSession所在層與BLL層之間的依賴。
在數據訪問接口層jygt.AutoWeightSystem.IDAL中添加新項目接口IDbSession,代碼如下:

這樣整個設計方案程序代碼在抽象與解耦方面性能得以很大改善。
2.2.1 Spring.Net 與MVC 配合使用
目的是把控制器下的生成B L L 實例的代碼,如userInfoBLL由

2.2.2 配置UI 層下的web.config 文件

2.2.3 修改UI 層下的Global.asax 文件的繼承類先添加Spring.net的引用。

2.2.4 在Config 文件夾下新建BLLs.xml
其配置如下。

這兩個X M L 配置語句順序不能對調,因為controllers.x ml中用到B L Ls.x ml中的內容,即controllers.xml配置文件需要引用(ref="UserInfoBLL")UserInfoBLL類,而UserInfoBLL類在BLLs.xml中配置。
綜上,由2.1節和2.2節,基于DAL層到BLL層的解耦、BLL層到UI層的解耦,如圖3所示。

圖3 DAL 層到BLL 層及BLL 層到UI 層的解耦過程示意圖
2.3.1 設計IDAL 的T4 模板IDALs.tt[5]

2.3.2 設計DAL層下的T4模板IDbSession.tt

2.3.3 設計EFDAL 的T4 模板DALs.tt
復制IDALs.tt一份到jygt.AutoWeightSystem.EFDAL項目下,并重命名為DALs.tt。修改DALs.tt文件如下。


2.3.4 設計DbSession 的T4 模板DbSession.tt
復制DALs.tt一份到jygt.AutoWeightSystem.DALFactoty項目下,并重命名為Dbsession.tt。修改Dbsession.tt文件代碼,方法與設計DALs.tt類似,代碼省略。
2.3.5 設計StaticDALFactory的 T4 模板StaticDALFactory.tt代碼省略。
2.3.6 設計IBLL 的T4 模板IBLL.tt
復制一份DbSession.tt到jygt.AutoWeightSystem.IBLL項目下,重命名為IBLL.tt并修改代碼。方法與設計DALs.tt類似,代碼省略。
保存下模板,即可生成相應的類。
2.3.7 設計BLL 的T4 模板BLL.tt
復制一份IBLL.tt到jygt.AutoWeightSystem.BLL項目下,把那個重命名為BLL.tt并修改代碼,方法與設計DALs.tt類似,代碼省略。
2.3.8 設計UI層下controllers.xml的T4 模板BLLxmlSpring.tt
到jygt.AutoWeightSystem.IBLL項目復制一份IBLL.tt到當前項目jygt.AutoWeightSystem.IBLL下,并重命名為BLLxmlSpring.tt并進行修改,方法與設計DALs.tt類似,代碼省略。
保存下模板,即可生成相應的XML文件。
最后,單擊生成---轉換所有T4模板,所有層的相應代碼就自動生成。
1.打開UserInfo的View頁面Index.cshtml,刪除body中間的所有內容;
2.復制jquery-easyui-1.3.1文件到項目的Content文件夾下[6];
3.在前臺添加展示數據表格的table元素;
4.添加添加樣式和js腳本等;


4. 角色管理、權限管理設計
與上節用戶管理設計類似進行角色管理、權限管理設計。整個權限管理系統的軟件結構如圖4所示。

圖4 權限管理系統的軟件結構
系統權限管理測試方案:
1.給用戶管理設置角色。用戶管理:勾選“高級管理員”角色;
2.給權限管理設置角色。權限管理:勾選“高級管理員”“管理員”角色;
3.用戶登錄測試當以高級管理員admin登錄時,桌面的圖標有用戶管理、權限管理、角色管理圖標,可執行相關操作;當用戶以管理員ZhangSan身份登錄時,桌面的圖標只有權限管理、角色管理可執行相關操作,沒有用戶管理圖標,不能執行用戶管理相關操作。
經上述操作測試和試運行,本項目基于MVC的權限管理系統實現了權限管理的功能。