程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> .NET框架下ORM的一個輕量高效替代方案

.NET框架下ORM的一個輕量高效替代方案

編輯:關於.NET

從最初做JAVA開發到現在致力於.NET平台,經手的大大小小的項目也不在少數。剛開始每寫成一個程序還能獲得不少的成就感,但隨著開發年限的增加、項目代碼行的增加,寫代碼更多時候變成一種糊口的工具而非興趣時,越來越被大量相似的SQL攪得頭暈腦脹,尤其維護舊程序時,對SQL的調試更是讓人頭大。於是,一直致力於找出一個方法,可以不用每次都去編寫那些煩人的SQL。

答案是肯定的,JAVA平台下有個Hibernate的ORM框架,它應該是最早的一個成熟的ORM軟件,貌似可以解決我的問題。迫不及待的下載、使用MyEclipse去寫測試程序,卻發現並不如想象中的好,對我來說,最大的障礙在於那個XML配置文件。借助於IDE,配置工作或許還不是太繁瑣,但脫離IDE之後,我發現對這個配置文件維護的困難絕對不在直接維護SQL命令之下。當然,好處還是有的,比如不用去調試每一條SQL。

雖然不太情願,但畢竟脫離IDE的情況還是很少,所以也就“愛用不用”地用了一段時間。

之後,機緣巧合的轉向.NET平台,從.NET Framework 1.1和VS2003開始,到現在的.NET Framework 2.0和VS2005,隨著在.NET平台開發經驗的日漸豐富,對C#特性越來越全面的了解,終於決定要自己寫一個更加符合C#口味的ORM框架,完全的面向對象,更加簡潔,更加高效,對IDE的智能感知支持更好(早期綁定) 。

一起來看看它的工作方式。

假設有一個員工表,字段為 id,employee_id,name,department_id

有一個實體類EmployeeInfo與上表各字段對應

現在我們需要為這個表寫一個訪問類,提供對數據庫的增、刪、改、查工作。

下面是實現以上功能的所有代碼:

public class EmployeeTable : TableAccess<EmployeeInfo> {
         internal override ColumnParameter[] FillColumnParameters(EmployeeInfo entity) {
             return base.BuildColumnParameter(
                 entity.ID,
                 entity.EmployeeID,
                 entity.Name,
                 entity.DepartmentID
             );
         }
         public override string TableName {
             get { return "employee_table"; }
         }
         public override TableColumnCollection TableColumns {
             get {
                 TableColumnCollection list = new TableColumnCollection(4);
                 list.AddRange(new TableColumn[] {
                     new TableColumn("id", true), // 自增只讀字段
                     new TableColumn("employee_id"),
                     new TableColumn("name"),
                     new TableColumn("department_id")
                 });
                 return list;
             }
         }
         internal override EmployeeInfo BuildEntity(MySqlDataReader reader, int startIndex) {
             EmployeeInfo info = new EmployeeInfo();
             info.ID = reader.GetInt32(0);
             info.EmployeeID = reader.GetString(1);
             info.Name = reader.GetString(2);
             info.DepartmentID = DataReadyUtility.GetInt32(reader,3);
             return info;
         }

}

從上面的代碼可以看出,對一個獨立表的訪問,只需重寫抽象基類的4個方法即可,可實現以下功能:

* 按主鍵獲取一個數據行 GetByPrimaryKey(object)

* 獲取數據表的所有記錄 GetAll()

* 查詢 Search(SearchConditionCollection, ...)

* 分頁查詢 Search(SearchConditionCollection, int, int, ...)

* 保存 Save(EmployeeInfo)

* 按主鍵值修改 Modify(...)

* 按條件修改 Modify(SearchConditionCollection, ...)

* 按主鍵刪除 Delete(...)

* 按查詢條件刪除 Delete(SearchConditionCollection, ...)

下面的代碼是對EmployeeTable類的擴充,使它具有足夠多的功能:

public class EmployeeTable : TableAccess<EmployeeInfo> {
     // 修改員工名字
     public int ChangeName(int id, string name) {
         EmployeeInfo info = new EmployeeInfo();
         info.Name = name;
         // 使用ModifyBounds.None表示僅修改後面指定的字段 TableColumns["name"]
         return base.Modify(id, info, ModifyBounds.None, TableColumns["name"]);
     }

     // 按名字獲取員工,不分頁 
     public IList<EmployeeInfo> GetByName(string name) {
         SearchConditionCollection filter = new SearchCoditionCollection();
         // 按Like查詢name字段
         filter.add(new SearchCondition("name", new ColumnComparison(SqlOperator.Like, name)));
         return base.Search(filter);
     }

     // 按名字獲取員工,並分頁 。輸出不分頁情況下的記錄總數,供前台分頁使用
     public IList<EmployeeInfo> GetByName(string name, int pageSize, int pageIndex, out int itemCount) {
         SearchConditionCollection filter = new SearchCoditionCollection();
         // 按Like查詢name字段
         filter.add(new SearchCondition("name", new ColumnComparison(SqlOperator.Like, name)));
         return base.Search(filter, pageSize, pageIndex, out itemCount);
     }
}

最後就是對上面類各個方法的調用了,以實現項目的需求。

public class EmployeeTableTest {
     void Test() {

         EmployeeTable employeeDAL = new EmployeeTable();
         SearchConditionCollection filter = new SearchConditionCollection(); // 查詢條件生成器

         // 保存一個員工
         EmployeeInfo employee = new EmployeeInfo();
         employee.Name = "wfyfngu";
         employee.DepartmentID = 4;
         employeeDAL.Save(employee);

         // 獲取ID為1的員工
         EmployeeInfo info = employeeDAL.GetByPrimaryKey(1);

         // 查詢所有員工
         IList<EmployeeInfo> all = employeeDAL.GetAll();

         // 分頁查詢
         int itemCount;
         IList<EmployeeInfo> pagedSource = employeeDAL.Search(null,10,1,out itemCount);

         // 修改ID為1的員工的名字
         employeeDAL.ChangeName(1, "wfyfngu");

         // 考慮到項目分層,業務邏輯層應該對數據庫字段一無所知
         // 所以,下面演示的方法僅僅出於演示目的,將字段名硬編碼到方法中

         // 刪除ID為 1 2 5 7 的用戶
         filter.Add(new SearchCondition(
             "user_id",
             new ColumnComparison(SqlOperator.In, 1,2,5,7)
         ));
         employeeDAL.Delete(filter);

         // 查詢名字以wfy開頭的員工,並分頁
         filter.Clear();
         filter.Add(new SearchCondition(
             "name",
             new ColumnComparison(SqlOperator.StartWith, "wfy")
         ));
         IList<EmployeeInfo> result = employeeDAL.Search(filter,10,1,out itemCount);

     }
}

其它功能,如簡單的聯表查詢,視圖查詢等不一一列舉。

附件說明:附件為本人編寫的ORM替代框架,針對MySql編寫,由於Cache功能涉及到另一個類庫,所以在附件中去除了,需要的可以自己加入。

幾個主要類源碼:

ReadonlyTableAccess<T>
TableAccess<T>
JoinTableAccess<T>

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved