個人覺得寫程式最快的方式就是「複製、貼上、修改」,但前題是複製的來源程式碼最好是整理過的,不然很可能變成 -複製混亂、貼上混亂、修改更混亂-,造成後續維護的麻煩。
針對指令資訊類別 (DataAccessCommandInfo),我把開發過程中自己常用的格式整理成一份 DemoCommandInfos.cs (放在資料層函式庫的 namespace Common.DataAccess.DemoCommandInfos,只是方便自己需要時隨時打開來用),
以下說明,
DemoCommandInfos.cs 裡面放了4種基本的指令資訊類別格式,
/// <summary> /// 1. 無參數 /// </summary> public class spDemo_WoPara : IDataAccessCommandInfo { public CommandType GetCommandType() { return CommandType.StoredProcedure; } public string GetCommandText() { return "dbo.spDemo_WoPara"; } } /// <summary> /// 2. 有參數 /// </summary> public class spDemo_WithPara : IDataAccessCommandInfo { // DataAccessCommand 會使用欄位變數當做 SqlParameter 的產生來源(使用名稱、值);屬性不包含在其中。 // 輸出參數請加上屬性 [OutputPara] public int pa1; public string pa2; public CommandType GetCommandType() { return CommandType.StoredProcedure; } public string GetCommandText() { return "dbo.spDemo_WithPara"; } } /// <summary> /// 3. 有參數,輸出參數內容 /// </summary> public class spDemo_WithOutputPara : IDataAccessCommandInfo { // DataAccessCommand 會使用欄位變數當做 SqlParameter 的產生來源(使用名稱、值);屬性不包含在其中。 // 輸出參數請加上屬性 [OutputPara] public int pa1; public string pa2; public int ListMode; public int BeginNum; public int EndNum; public string SortField; public bool IsSortDesc; [OutputPara] public int RowCount; public CommandType GetCommandType() { return CommandType.StoredProcedure; } public string GetCommandText() { return "dbo.spDemo_WithOutputPara"; } } /// <summary> /// 4. 有參數(加權限參數),輸出參數內容 /// </summary> public class spDemo_WithOutputParaAndAuthPara : IDataAccessCommandInfo { // DataAccessCommand 會使用欄位變數當做 SqlParameter 的產生來源(使用名稱、值);屬性不包含在其中。 // 輸出參數請加上屬性 [OutputPara] public int pa1; public string pa2; public int ListMode; public int BeginNum; public int EndNum; public string SortField; public bool IsSortDesc; public bool CanReadSubItemOfOthers; public bool CanReadSubItemOfCrew; public bool CanReadSubItemOfSelf; public string MyAccount; public int MyDeptId; [OutputPara] public int RowCount; public CommandType GetCommandType() { return CommandType.StoredProcedure; } public string GetCommandText() { return "dbo.spDemo_WithOutputParaAndAuthPara"; } }
之前在資料層基本的呼叫方式內文中提到 SP 有「讀取資料用、新增用、更新用、刪除用」的差別,
不過對於指令資訊類別來說只有「有無參數、有無輸出型參數」的差別,上述 1~3 的類別格式範例就是這樣的差別而已。第 4 種類別格式範例只是為了個人方便,不想每次都重打 CanReadSubItemOfOthers, CanReadSubItemOfCrew, CanReadSubItemOfSelf, MyAccount, MyDeptId 這幾個成員變數,所以才多出這一種。
接下來我要示範當 SP 寫好之後,建立對應的指令資訊類別的步驟。
這次以新增員工身分資料來做為範例,下列是其 SP 的名稱與參數資訊,
-- ============================================= -- Author: <lozen_lin> -- Create date: <2017/11/11> -- Description: <新增員工身分資料> -- ============================================= create procedure dbo.spEmployeeRole_InsertData @RoleName nvarchar(20) ,@RoleDisplayName nvarchar(20) ,@SortNo int ,@PostAccount varchar(20) ,@CopyPrivilegeFromRoleName nvarchar(20) ,@RoleId int output as
開始建立指令資訊類別,
Step 1.
SP 有參數而且有輸出型的參數,到 DemoCommandInfos.cs 複製第 3 種的範例程式碼,並且貼上到 EmployeeAuthority.cs 的 namespace Common.DataAccess.EmployeeAuthority 區塊裡(因為這個 SP 歸類在帳號與權限系統)。
在 Visual Studio 之中點選綠框區可選擇 class name 快速跳到指定的程式碼 (這裡使用 Visual Studio Community 2015) |
/// <summary> /// 有參數,輸出參數內容 /// </summary> public class spDemo_WithOutputPara : IDataAccessCommandInfo { // DataAccessCommand 會使用欄位變數當做 SqlParameter 的產生來源(使用名稱、值);屬性不包含在其中。 // 輸出參數請加上屬性 [OutputPara] public int pa1; public string pa2; public int ListMode; public int BeginNum; public int EndNum; public string SortField; public bool IsSortDesc; [OutputPara] public int RowCount; public CommandType GetCommandType() { return CommandType.StoredProcedure; } public string GetCommandText() { return "dbo.spDemo_WithOutputPara"; } }
Step 2.
從 SP 原始碼複製中、英文名稱並且取代類別的註解、類別名稱和 GetCommandText() 內容。
/// <summary> /// 新增員工身分資料 <--改這邊 /// </summary> public class spEmployeeRole_InsertData : IDataAccessCommandInfo // <--改這邊 { // DataAccessCommand 會使用欄位變數當做 SqlParameter 的產生來源(使用名稱、值);屬性不包含在其中。 // 輸出參數請加上屬性 [OutputPara] public int pa1; public string pa2; public int ListMode; public int BeginNum; public int EndNum; public string SortField; public bool IsSortDesc; [OutputPara] public int RowCount; public CommandType GetCommandType() { return CommandType.StoredProcedure; } public string GetCommandText() { return "dbo.spEmployeeRole_InsertData"; // <--改這邊 } }
Step 3.
從 SP 原始碼複製參數名單,換掉類別裡的成員變數。
/// <summary> /// 新增員工身分資料 /// </summary> public class spEmployeeRole_InsertData : IDataAccessCommandInfo { // DataAccessCommand 會使用欄位變數當做 SqlParameter 的產生來源(使用名稱、值);屬性不包含在其中。 // 輸出參數請加上屬性 [OutputPara] @RoleName nvarchar(20) // <--改這邊 ,@RoleDisplayName nvarchar(20) ,@SortNo int ,@PostAccount varchar(20) ,@CopyPrivilegeFromRoleName nvarchar(20) [OutputPara] ,@RoleId int output public CommandType GetCommandType() { return CommandType.StoredProcedure; } public string GetCommandText() { return "dbo.spEmployeeRole_InsertData"; } }
Step 4.
把類別裡的成員變數一個一個改為 c# 格式,完成!
/// <summary> /// 新增員工身分資料 /// </summary> public class spEmployeeRole_InsertData : IDataAccessCommandInfo { // DataAccessCommand 會使用欄位變數當做 SqlParameter 的產生來源(使用名稱、值);屬性不包含在其中。 // 輸出參數請加上屬性 [OutputPara] public string RoleName; // <--改這邊 public string RoleDisplayName; // <--改這邊 public int SortNo; // <--改這邊 public string PostAccount; // <--改這邊 public string CopyPrivilegeFromRoleName; // <--改這邊 [OutputPara] public int RoleId; // <--改這邊 public CommandType GetCommandType() { return CommandType.StoredProcedure; } public string GetCommandText() { return "dbo.spEmployeeRole_InsertData"; } }
以上就是個人每次在 SP 寫好之後,要建立對應的指令資訊類別所做的事情,每次4步驟完成,最後寫好的所有帳號與權限相關指令資訊類別就長這樣子 EmployeeAuthority.cs。
(其實這4步驟應該可以自製一個 code generator 連線到資料庫,點選 SP 來產生 c# 程式碼,這個嘛...等我哪天覺得複製、貼上、修改多到累了再說吧。)
新增資料層程式只需要給個 SP 名稱、寫一次同樣的參數資訊就完成了,這樣真的很省事!
但需求總會出現例外,萬一想要客製化指令資訊類別的時候該怎麼做呢?例如:我想直接在資料層寫 sql script、我想在資料層開啟交易執行多個 SP。
後續我會繼續介紹~
沒有留言:
張貼留言