天天看點

淺談C#資料庫業務的分層架構與執行個體解析一.前言 二.分層式架構      三.執行個體解析  

一.前言

        假設有這麼一個需求:從連接配接某個資料庫并從中查詢某個表的資訊,放到程式的位置進行存儲。

        想必一開始的寫法會是下面這樣:

#region 根據資料庫添加内容
        public void FillGridView(DataGridView MyGrid, string Upname, int Count)
        {
            //建立指令
            SqlCommand com = new SqlCommand();
            com.Connection = MyConnection;
            com.CommandType = CommandType.Text;

            //sql語句
            com.CommandText = "select * from TAB_ACCESS where ACCESS_LEVEL=1 AND ACCESS_NAME='" + Upname + "'";

            //執行語句
            SqlDataReader reader = com.ExecuteReader();
            string name = null;
            string score = null;
            //讀取資料
            while (reader.Read())
            {
                name = reader["ACCESS_NAME"].ToString();
                score = reader["ACCESS_SCORE"].ToString();
            }
            reader.Close();

            //處理讀到的資料(實際業務)
            int Sum = 0;
            for (int j = 0; j < Count; j++)
            {
                Sum += RootCount[j];
                if (RootCount[j] == 0)
                    Sum++;
            }
            if (RootCount[Count] > 0)
            {
                for (int i = 0; i < RootCount[Count]; i++)
                {
                    MyGrid.Rows[Sum + i].Cells[0].Value = name;
                    MyGrid.Rows[Sum + i].Cells[1].Value = score;
                }
            }
            else
            {
                MyGrid.Rows[Sum].Cells[0].Value = name;
                MyGrid.Rows[Sum].Cells[1].Value = score;
            }
        }
        #endregion
           

        在這一個方法中,能完成業務的所有需求:連接配接資料庫,讀資料,處理資料。 程式能良好運作,沒有什麼問題。

        這時,若需要擴充新的業務,或是在後期的運維中需要修改,那麼問題就出現了:方法中各自的邏輯都緊緊糾纏在一起,彼此間互相依賴,誰都是不可替換的。隻能寫新的方法,也就是重新完成連接配接資料庫,讀資料,處理資料的操作。這無疑加大了開發和維護的成本,效率很低。

        本着 “高内聚,低耦合” 的思想,我們要想辦法降低各個業務的耦合性,連接配接資料庫歸連接配接資料庫,讀資料歸讀資料,處理資料歸處理資料,大家進水不犯河水。于是,在項目中,我們可以考慮采用分層式架構。

 二.分層式架構      

最常見的分層架構為(參考百度百科描述):

1.表示層(USL - User Show Layer)

        位于最上層。用于顯示資料和接收使用者輸入的資料,為使用者提供一種互動式操作的界面。

2.業務邏輯層(Business Logic Layer)

        業務邏輯層是系統架構中展現核心價值的部分。它的關注點主要集中在業務規則的制定、業務流程的實作等與業務需求有關的系統設計。

        業務邏輯層在體系架構中的位置很關鍵,它處于資料通路層與表示層中間,起到了資料交換中承上啟下的作用。由于層是一種弱耦合結構,層與層之間的依賴是向下的,底層對于上層而言是“無知”的,改變上層的設計對于其調用的底層而言沒有任何影響。如果在分層設計時,遵循了面向接口設計的思想,那麼這種向下的依賴也應該是一種弱依賴關系。因而在不改變接口定義的前提下,理想的分層式架構,應該是一個支援可抽取、可替換的“抽屜”式架構。正因為如此,業務邏輯層的設計對于一個支援可擴充的架構尤為關鍵,因為它扮演了兩個不同的角色。對于資料通路層而言,它是調用者;對于表示層而言,它卻是被調用者。依賴與被依賴的關系都糾結在業務邏輯層上,如何實作依賴關系的解耦,則是除了實作業務邏輯之外留給設計師的任務。

3.資料層(DAL - Data Access Layer)

        資料通路層:有時候也稱為是持久層,其功能主要是負責資料庫的通路,可以通路資料庫、二進制檔案、文本文檔或是XML文檔。簡單的說法就是實作對資料表的Select,Insert,Update,Delete的操作。

優點

1、開發人員可以隻關注整個結構中的其中某一層;

2、可以很容易的用新的實作來替換原有層次的實作;

3、可以降低層與層之間的依賴;

4、有利于标準化;

5、利于各層邏輯的複用。

6、結構更加的明确

7、在後期維護的時候,極大地降低了維護成本和維護時間

缺點

1、降低了系統的性能。這是不言而喻的。如果不采用分層式結構,很多業務可以直接造訪資料庫,以此擷取相應的資料,如今卻必須通過中間層來完成。

2、有時會導緻級聯的修改。這種修改尤其展現在自上而下的方向。如果在表示層中需要增加一個功能,為保證其設計符合分層式結構,可能需要在相應的業務邏輯層和資料通路層中都增加相應的代碼。

3、增加了開發成本。

三.執行個體解析

拿最近做的資料庫項目的架構來講,初步的分層架構如下:

淺談C#資料庫業務的分層架構與執行個體解析一.前言 二.分層式架構      三.執行個體解析  

在實際應用中的表現是這樣的:

淺談C#資料庫業務的分層架構與執行個體解析一.前言 二.分層式架構      三.執行個體解析  

Interface 為接口層。在此定義資料庫通路接口。

DataModel 為資料模型層。在此定義各種類和結構體用于存儲資料(在架構中可以去掉)。

DAL為資料通路層。資料庫的連接配接以及所有對資料庫的增删改查都在此實作。

BLL為業務邏輯層。讀到的資料在這裡進行處理,比如将存儲到某個結構體或類中。

簡單舉例

假設資料庫中存在一個部門表(TAB_DEPART) , 我們需要從中查詢所有記錄,存到預先定義好的List<DepartmentRecord>中。

操作流程如下圖:

淺談C#資料庫業務的分層架構與執行個體解析一.前言 二.分層式架構      三.執行個體解析  

Interface定義:

namespace BSH_DBA.Interface
{
    /// <summary>
    /// UserDAL接口 
    /// </summary>
    public interface IUserDAL  
    {
        /// <summary>
        /// 查詢所有部門記錄
        /// </summary>
        /// <param name="conn">連接配接字段</param>
        /// <returns>DataTable:成功;其他:失敗</returns>
        DataTable SelectDepartment(string conn);
    }
}
           

DAL中繼承接口并寫詳細資料庫操作:

namespace BSH_DBA.DAL
{
    /// <summary>
    /// 使用者管理子產品庫資料操作
    /// </summary>
    public class UserDAL : IUserDAL
    {
        /// <summary>
        /// 查詢所有部門記錄
        /// </summary>
        /// <param name="conn">連接配接字段</param>
        /// <returns>DataTable:成功;其他:失敗</returns>
        public DataTable SelectDepartment(string conn)
        {
            StringBuilder MysqlCommand = new StringBuilder();
            try
            {
                MysqlCommand.Append(string.Format(@"select * from {0}", NamedConfig.TAB_DEPART));
                DataTable dt = MySqlHelper.ExecuteDataset(conn, CommandType.Text, MysqlCommand.ToString()).Tables[0];
                return dt;
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                return null;
            }

        }
}
           

BAL中調用接口讀到資料并存儲:

namespace BSH_DBA.BLL
{
    /// <summary>
    /// 使用者業務
    /// 注:使用者包括服務人員、管理者、超級管理者、Admin
    /// </summary>
    public class UserBLL
    {
        private static readonly IUserDAL iUser = new UserDAL();
        /// <summary>
        /// 查詢所有部門記錄
        /// </summary>
        /// <param name="conn">連接配接字段</param>
        /// <param name="list_record">輸出:部門清單</param>
        /// <returns>0:成功;其他:失敗</returns>
        public static int SelectDepartment(string conn, List<DepartmentRecord> list_record)
        {
            //調用接口,讀取資料
            DataTable dt = iUser.SelectDepartment(conn);
            if(dt == null)
            {
                return 1;
            }
            //周遊DataTable,将裡面資料存到List中
            foreach(DataRow dr in dt.Rows)        
            {
                string id = dr["depart_id"].ToString(); 
                string name = dr["depart_name"].ToString();
                string upid = dr["depart_upid"].ToString();
                DepartmentRecord drecord = new DepartmentRecord(id,name,upid);
                list_record.Add(drecord);
            }
            return 0;
        }
    }
}



           

以上便是以分層架構完成的資料庫業務操作。供參考。