0 綜述 1 MVP各模塊規範 1.1 實體模塊規範 1.1.1 命名規範 實體類封裝到單獨的DLL中,DLL命名遵循<ProjectName>.DataEntity。資料庫實體類名遵循:資料庫表名去掉複數尾碼,如“s”、“es”等(資料庫表的名稱必須是名詞複數)。 1.1.2 架構規範 實體模塊中 ...
0 綜述
1 MVP各模塊規範
1.1 實體模塊規範
1.1.1 命名規範
實體類封裝到單獨的DLL中,DLL命名遵循<ProjectName>.DataEntity。資料庫實體類名遵循:資料庫表名去掉複數尾碼,如“s”、“es”等(資料庫表的名稱必須是名詞複數)。
1.1.2 架構規範
實體模塊中必須包含一個泛型實體介面,供所有數據實體類實現該介面,該介面所繼承介面亦為各實體類所統一實現(例如該介面實現自IEquatable<T>),該介面泛型參數必須為本介面類型,該介面可以不聲明任何成員。例如:
1 namespace TestProj.DataEntity 2 { 3 public interface ITestProjEntity<T> : IEquatable<T> 4 where T : ITestProjEntity<T> 5 { 6 } 7 }
該介面用於規範實體類編寫。
該介面命名規範遵循:I+<項目名>+Entity形式,該介面必須為泛型介面,該介面泛型參數必須是本介面。實體類只映射資料庫實際結構,實體類之間主外鍵關聯用程式邏輯維護,即:不採用實體間依賴的方式表示主外鍵關聯(實體類不包含其他實體類的實例對象、列表、集合等)。
實體類示例代碼如下:
public class Patient : IOpenTCMEntity<Patient> { public string ID { get; set; } //主鍵ID public string Name { get; set; } //姓名 public bool Equals(Patient other) { if (other == null) { return false; } if (other == this) { return true; } bool res = other.ID == ID && other.Name == Name; return res; } }
1.2 資料庫訪問介面
1.2.1 命名規範
資料庫訪問介面必須封裝到單獨的DLL中,DLL命名遵循 I + <ProjectName>.DataOperate。資料庫訪問類命名遵循:I + <相對應實體類命名> + “DAO”。
1.2.2 架構規範
資料庫訪問介面必須包含一個泛型介面,該泛型介面用於統一聲明所有公共的資料庫ACID函數,該介面泛型參數必須是資料庫實體類所共同實現的介面類型,該介面命名必須為IBaseDAO。示例代碼如下:
1 public interface IBaseDAO<E> 2 where E : IOpenTCMEntity<E> 3 { 4 /// <summary> 5 /// 是否存在ID所對應的記錄 6 /// </summary> 7 /// <param name="id"></param> 8 /// <returns></returns> 9 bool Exists(string id); 10 /// <summary> 11 /// 是否存在參數對象所描述的記錄(屬性為空表示該屬性不作為查詢條件) 12 /// </summary> 13 /// <param name="condition"></param> 14 /// <returns></returns> 15 bool Exists(E condition); 16 /// <summary> 17 /// 將參數描述的實體對象添加到資料庫中 18 /// </summary> 19 /// <param name="po"></param> 20 /// <returns></returns> 21 bool AddEntity(E po); 22 /// <summary> 23 /// 將參數描述的實體對象集合添加到資料庫中 24 /// </summary> 25 /// <param name="pos"></param> 26 /// <returns></returns> 27 bool AddEntity(List<E> pos); 28 /// <summary> 29 /// 根據ID從資料庫中刪除實體 30 /// </summary> 31 /// <param name="id"></param> 32 /// <returns></returns> 33 bool DelEntity(string id); 34 /// <summary> 35 /// 依據參數描述的資料庫記錄更新資料庫, 36 /// 本操作需要先從資料庫獲取具體的對象。 37 /// </summary> 38 /// <param name="po"></param> 39 /// <returns></returns> 40 bool UpdateEntity(E po); 41 /// <summary> 42 /// 依據參數描述的對象為條件,獲取記錄數。 43 /// </summary> 44 /// <param name="condition"></param> 45 /// <returns></returns> 46 long GetCount(E condition); 47 /// <summary> 48 /// 獲取總記錄數 49 /// </summary> 50 /// <returns></returns> 51 long GetCount(); 52 /// <summary> 53 /// 獲取所有實體對象集合 54 /// </summary> 55 /// <returns></returns> 56 List<E> SelectEntity(); 57 /// <summary> 58 /// 獲取分頁對象集合 59 /// </summary> 60 /// <param name="beg"></param> 61 /// <param name="len"></param> 62 /// <returns></returns> 63 List<E> SelectEntity(int beg, int len); 64 /// <summary> 65 /// 根據ID獲取一個實體對象 66 /// </summary> 67 /// <param name="id"></param> 68 /// <returns></returns> 69 E SelectEntity(string id); 70 /// <summary> 71 /// 依據條件獲取實體集合 72 /// </summary> 73 /// <param name="condition"></param> 74 /// <returns></returns> 75 List<E> SelectEntity(E condition); 76 }
針對每個資料庫表創建對應的數據訪問介面,該介面繼承自IBaseDAO,泛型參數為該數據表對應的實體類。代碼示例如下:
1 public interface ITestDAO:IBaseDAO<Test> 2 { 3 }
1.3 數據業務介面規範
1.3.1 命名規範
業務介面必須封裝到單獨的DLL中,DLL命名遵循<ProjectName>.DataBiz。業務類命名遵循:相對應實體類+"BO"。
1.3.2 架構規範
資料庫業務介面必須包含一個公用的泛型介面,該泛型介面用於統一聲明所有公共的資料庫ACID函數,該介面泛型參數必須是資料庫實體類所共同實現的介面類型,和一個用於訪問資料庫的IBaseDAO類型屬性。示例代碼如下:
1 public interface IBaseBO<E, DAO> 2 where E : IOpenTCMEntity<E> 3 where DAO : IBaseDAO<E> 4 { 5 /// <summary> 6 /// 資料庫操作對象 7 /// </summary> 8 DAO DbOperator { get; set; } 9 /// <summary> 10 /// 是否存在ID所對飲的記錄 11 /// </summary> 12 /// <param name="id"></param> 13 /// <returns></returns> 14 bool Exists(string id); 15 /// <summary> 16 /// 是否存在參數對象所描述的記錄(屬性為空表示該屬性不作為查詢條件) 17 /// </summary> 18 /// <param name="condition"></param> 19 /// <returns></returns> 20 bool Exists(E condition); 21 /// <summary> 22 /// 將參數描述的實體對象添加到資料庫中 23 /// </summary> 24 /// <param name="po"></param> 25 /// <returns></returns> 26 bool AddEntity(E po); 27 /// <summary> 28 /// 將參數描述的實體對象集合添加到資料庫中 29 /// </summary> 30 /// <param name="pos"></param> 31 /// <returns></returns> 32 bool AddEntity(List<E> pos); 33 /// <summary> 34 /// 根據ID從資料庫中刪除實體 35 /// </summary> 36 /// <param name="id"></param> 37 /// <returns></returns> 38 bool DelEntity(string id); 39 /// <summary> 40 /// 依據參數描述的資料庫記錄更新資料庫, 41 /// 本操作需要先從資料庫獲取具體的對象。 42 /// </summary> 43 /// <param name="po"></param> 44 /// <returns></returns> 45 bool UpdateEntity(E po); 46 /// <summary> 47 /// 依據參數描述的對象為條件,獲取記錄數。 48 /// </summary> 49 /// <param name="condition"></param> 50 /// <returns></returns> 51 long GetCount(E condition); 52 /// <summary> 53 /// 獲取總記錄數 54 /// </summary> 55 /// <returns></returns> 56 long GetCount(); 57 /// <summary> 58 /// 獲取所有實體對象集合 59 /// </summary> 60 /// <returns></returns> 61 List<E> SelectEntity(); 62 /// <summary> 63 /// 獲取分頁對象集合 64 /// </summary> 65 /// <param name="beg"></param> 66 /// <param name="len"></param> 67 /// <returns></returns> 68 List<E> SelectEntity(int beg, int len); 69 /// <summary> 70 /// 根據ID獲取一個實體對象 71 /// </summary> 72 /// <param name="id"></param> 73 /// <returns></returns> 74 E SelectEntity(string id); 75 /// <summary> 76 /// 依據條件獲取實體集合 77 /// </summary> 78 /// <param name="condition"></param> 79 /// <returns></returns> 80 List<E> SelectEntity(E condition); 81 }
針對每個資料庫表創建對應的數據訪問介面,該介面繼承自IBaseDAO,泛型參數為該數據表對應的實體類。代碼示例如下:
public interface ISymptomBO : IBaseBO<Pathology, ISymptomDAO> { //TODO:Type your specific business logical code }
該介面中可以聲明特定與該數據表的特定業務函數、屬性。
1.4 數據訪問模塊
1.4.1 命名規範
數據訪問模塊必須封裝為單獨的DLL,DLL文件命名規範遵循<項目名>.DataOperate,數據訪問類遵循 <表名單數形式> + DAO 的命名規範。
1.4.2 架構規範
數據訪問模塊需要引用System.ComponentModel.Composition命名空間。數據訪問模塊若使用EF6,則必須包含一個數據上下文類,該類命名個規範為<Project>Context,該類用於提供EntityFramework6的數據上下文。
數據上下文類結構如下:
public class OpenTCMContext : DbContext { public OpenTCMContext() : base("TestConnStr") { } public DbSet<TestTableA> TestTableAContext { get; set; } public DbSet<TestTableA> TestTableBContext { get; set; } }
數據訪問類之間不互相依賴,每個數據訪問類實現自按資料庫表對應的數據訪問介面,並具備一個私有隻讀的數據上下文對象。數據訪問類每個實現自IBaseDAO的函數不互相引用。
數據訪問類若使用EF6的形式,就需要辯證的看待資料庫增刪改查的方式,某些簡單的資料庫操作若使用純EF6方式,資料庫交互數量級有按指數翻倍的可能。本文建議的資料庫訪問方式,儘量採用SQL,不涉及大量重覆操作資料庫的情況下,兼顧EF6的便捷操作。數據訪問類需要向MEF容器導出其自身,鑒於每個數據訪問介面皆對應一個單獨的實現類,這裡採用[Export(typeof(<父介面>))]的方式。
數據訪問類部分代碼示意如下:
[Export(typeof(ITestDAO))] public class TestDAO : ITestDAO { public TestDAO() { context = new OpenTCMContext(); } private readonly TestProjContext context; public bool Exists(string id) { var res = context.TestContext.SqlQuery("ID='{0}'", id); if (res.FirstOrDefault() == null) { return false; } int count = res.Count(); return count > 0; } //... }
1.5 資料庫業務模塊
1.5.1 命名規範
資料庫業務模塊必須封裝為單獨的DLL,DLL文件命名規範為<項目名>.DataBiz,資料庫業務類命名遵循<對應實體類名> + BO。
1.5.2 架構規範
資料庫業務類實現自其對應的業務介面,其必須實現介面規定的資料庫操作抽象介面對象屬性,並標註從MEF容器註入該對象實例。併在構造函數中顯式構建該介面對象。該類也需要向MEF容器導出其自身,供頂級業務構建其示例。資料庫業務類參考代碼示例如下:
[Export("TestBO", typeof(ITestBO))] public class TestBO : ITestBO { public TestBO() { var catalog = new DirectoryCatalog("./"); var container = new CompositionContainer(catalog); container.ComposeParts(this); } [Import] public ITestDAO DbOperator { get; set; } public bool Exists(string id) { return DbOperator.Exists(id); } //... }
2 總結
至此,一個基於.Net + MEF + EF6 的輕量級系統基礎架構就完成了。其中業務介面依賴於數據操作介面,業務模塊與數據操作模塊分別依賴於其所對應介面,具體模塊之間沒有依賴關係。各介面、具體模塊均需添加實體模塊的引用。