1. 程式人生 > >【C#】之七層登入程式碼詳解

【C#】之七層登入程式碼詳解

前言

  之前我有寫過一篇三層登入,應用三層,將介面處理、業務邏輯處理和資料訪問分別開來,能夠很好的減少登入系統中各個模組之間的耦合度,使的系統更加可維護、可複用和可擴充套件。而七層登入是在三層基礎之上的更完美的改進,他除了主三層中有的UI層、BLL層、DAL層和Enitity層(實體層)之外,還引入了Facade層(外觀層)、IDAL層(介面層)、Factory層(工廠層)和SQLHelper類,使得三層更加獨立封閉,充分體現了面向物件程式設計。下面我們就來具體看一下七層到底是怎樣實現的。

一、新增加的層?

1、 Facade層(外觀層)

  外觀層應用了設計模式中的外觀模式

(為子系統中的一組介面提供一個一致的介面,此模式定義了一個高層介面,這個介面使得這一子系統更加容易使用),在七層中,它位於UI層與BLL層之間,在BLL層中可能有多可業務邏輯類,這些業務邏輯類被UI層呼叫,在沒有外觀層時,UI層每需要一個業務邏輯類就要例項化一個,帶有耦合性,擴充套件起來很不方便。應用外觀層之後,UI層直接將資料傳入外觀的某個方法中,由外觀去例項化業務邏輯類,這樣擴充套件的時候直接改變UI與外觀之間的連結就可以了,不需要對業務邏輯在進行處理,進一步減少了UI層與BLL層之間的耦合性。

2、Factory層(工廠層)

  工廠層應用了設計模式中的抽象工廠模式(提供一個建立一系列相關或相互依賴物件的介面,而無需指定他們具體的類)

,它位於BLL層與DAL層之間,在工廠層中應用了反射+配置檔案的資料訪問程式,由於BLL層可能要訪問多個DAL中的具體類,通過配置檔案連線BLL層要訪問的具體程式集(即DAL層),通過反射,反射出來BLL層要訪問的DAL層中的具體類,這樣就減少了BLL層與DAL層中相互依賴物件之間的耦合,直接由工廠去指定具體的類。

3、IDAL層(介面層)

  介面層的應用充分實現了介面隔離遠原則,它位於BLL層與DAL層之間,BLL層與DAL層中的類沒有必要直接通訊,當BLL層中的一個類需要呼叫DAL層中一個類的方法時,可以通過介面IDAL來轉發這個呼叫。

4、SQLHelper類

  這一層沒有單獨的名稱空間,可以將它看做是DAL層中的一個輔助類

,我們直接將它放在了DAL層,他的存在完全是為了減輕DAL層的負擔,我們知道DAL層是資料訪問層,所有參與資料庫的操作(連線、增、刪、改、查)都要放在其中,為了避免DAL層中每一個類都重複這些操作,我們就可以將對資料庫的具體操作單獨的封裝在一個SQLHelper類當中,作為一個模組存在,DAL中的其他類提出對資料庫的操作後,將操作要求傳入SQLHelper模組中,將結果在返回給提出要求的這個類。這樣一來減少的程式碼的冗餘,利於程式設計。

二、圖解

在這裡插入圖片描述
  我們在分析的時候,是按照資料流動的情況進行分析的,即UI——>Facade——>BLL——>Factory——>IDAL——>DAL——>SQLHelper,但是資料是貫穿於整個七層的,為了避免敲程式碼是後所引用的方法爆紅(前提是現將類都建好並命好名),我們在敲程式碼的時候的順序與分析的順序不一致,即Enitity——》IDAL——》DAL——》Factory——》BLL——》Facade——》UI,這樣只是為了方便書寫,當然,如果敲起來不順手的話,還可以從頭向後敲,每用到一個方法就去寫一個方法框架。

三、程式碼詳解

  按照我們分析的過程進行程式碼詳解。

Enitity層

namespace Enitity
{
    //實體層
    public class UserInfo
    {
        //定義使用者ID屬性    
        private int userid;
        public int UserID
        {
            get { return userid; }
            set { userid = value; }
        }

        //定義使用者密碼PassWord屬性 
        private string  password;
        public string PassWord
        {
          get { return password; }
          set { password = value; }
        }

    }

UI層

private void BtnLogin_Click(object sender, EventArgs e)
        {
            //判斷輸入不能為空
            if (TxtID.Text.Trim() == "")
            {
                MessageBox.Show("請輸入使用者名稱!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            if (TxtPassword.Text == "")
            {
                MessageBox.Show("請輸入密碼!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

            try
            {
                //例項化一個使用者實體user
                Enitity.UserInfo user = new Enitity.UserInfo();

                //接收控制元件傳來的使用者資訊
                user.UserID = Convert .ToInt32(TxtID.Text.Trim());
                //接收控制元件傳來的密碼資訊
                user.PassWord = TxtPassword.Text;

                //例項化外觀
                Facade.LoginFacade FLogin = new Facade.LoginFacade();

                //定義一個bool型的變數,用來接收是否查詢成功
                Boolean flag = false;

                //呼叫外觀的方法,返回給flag
                flag = FLogin.SelectUser(user);

                //判斷是否登入成功
                if (flag != false)
                {
                    MessageBox.Show("登入成功!");
                    this.Hide();

                    this.DialogResult = System.Windows.Forms.DialogResult.OK;
                    //例項化一個窗體
                    Form a = new Form();
                    a.Show();
                }
                else
                {
                    MessageBox.Show("使用者名稱或密碼錯誤!");
                }
            }
            catch (Exception)
            {
                throw;
            }
        }


    

Facade層

namespace Facade
{
    //外觀層
    public class LoginFacade
    {
        //將資料user從UI層傳入BLL層,提供返回值給flag
        public Boolean SelectUser(Enitity.UserInfo user )
        {       
            bool flag;

            //例項化一個B層
            BLL.LoginBLL userBLL = new BLL.LoginBLL();

            //將使用者資料傳入B層,返回值給flag
            flag = userBLL.UserBLL(user);

            return flag;
        }      
    }
}

BLL層

namespace BLL
{
    //業務邏輯層
    public class LoginBLL
    {
        //判斷使用者是否存在
        public bool UserBLL(Enitity.UserInfo user)
        {
            //例項化工廠
            Factory.LoginFactory fact = new Factory.LoginFactory();

            //呼叫工廠中的方法,例項化一個實現介面的內部類,將反射結果賦給idal
            IDAL.LoginIDAL idal = fact.CreateUser();//登入中,此時的idal反射的是dal中的LoginDAL類

            //接收D層的返回值
            DataTable table = idal.SelectUser(user);            

            bool flag;

            //返回資料表型別,如果行數=0,說明沒有符合該賬號密碼的使用者
            if (table.Rows.Count ==0)
            {
                flag = false;
            }
            else
            {
                flag = true;
            }

            //返回數值
            return flag;
        }
    }
}

Factory層

namespace Factory
{
    //工廠層
    public class LoginFactory
    {
        //接收來自配置檔案的資料,明確工廠要連結那一層
        string StrDB = System.Configuration.ConfigurationManager.AppSettings["DB"];
        
        //應用反射來獲取被呼叫的DAL層的具體操作類
        public IDAL.LoginIDAL CreateUser()
        {   
            //明確具體操作類
            string ClassName = StrDB + "." + "LoginDAL";

            //反射加工廠的應用——將在DAL層中用到的具體類反射到介面,說明那個類實現了這個介面
            return (IDAL.LoginIDAL)Assembly.Load(StrDB).CreateInstance(ClassName);

        }
    }
}

IDAL層

namespace IDAL
{
    public interface LoginIDAL
    {     
            //放置介面函式,判斷要登入的使用者是否在資料表中存在
            DataTable SelectUser(Enitity.UserInfo user);   
    }
}

DAL層

namespace DAL
{
    public class LoginDAL:IDAL.LoginIDAL
    {
        public DataTable SelectUser(Enitity.UserInfo user)
        {
            //例項化資料操作類,進行資料查詢,並獲取返回值
            SQLHelper sqlHelper = new SQLHelper();

            //選擇要查詢的資料型別,作為sqlCommand的引數
            SqlParameter[] sqlparams = {new SqlParameter ("@ID",user.UserID),
                                        new SqlParameter("@Password",user.PassWord )};

            //查詢語句
            string sql = "select * from Users where ID [email protected] AND [email protected]";

            //將查詢語句和要查詢的資料 傳入sqlHelper類中進行查詢操作
            DataTable table = sqlHelper.ExecuteQuery(sql,sqlparams,CommandType.Text);//CommandType.Text解釋SQL文字命令的字串

            return table;
        }
    }
}

SQLHelper類

namespace DAL
{
    //資料訪問層——資料操作類
    public class SQLHelper
    {        
        private SqlConnection conn = null;//定義資料連線操作
        private SqlCommand cmd = null;  //指定能在資料庫上執行的操作
        private SqlDataReader sdr = null; //定義一個讀取資料流的變數,從資料庫中只讀

        /// <summary>
        /// 資料庫連線
        /// </summary>
        public SQLHelper()//建構函式
        {
            string connStr = ConfigurationManager.AppSettings["connStr"];//ConnStr配置檔案中連線資料庫的關鍵字(字串)
           conn = new SqlConnection(connStr); //例項化一個連線
        }

        //將連線的資料庫開啟
        private SqlConnection GetConn()
        {
            if (conn.State == ConnectionState.Closed )//如果連線狀態為關閉,則開啟
            {
                conn.Open();
            }
            return conn;
        }
        
//只顯示執行程式碼,SQLHelper類中的其他資料庫操作省略

 	/// <summary>
        /// 執行帶引數的SQL查詢語句或儲存過程
        /// </summary>
        /// <param name="cmdText"></param>
        /// <param name="paras"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        public DataTable ExecuteQuery(string cmdText,SqlParameter[] paras,CommandType ct)
        {
            //例項化一個數據表
            DataTable  dt = new DataTable  ();

            //例項化出一個數據操作
            cmd = new SqlCommand(cmdText, GetConn ());//cmdText為傳進來的SQL命令,GetConn為一個開啟狀態的資料庫連線

            cmd.CommandType = ct;
            cmd.Parameters .AddRange (paras);//將要查詢的資料放入查詢語句中

            //cmd.ExecuteReader讀取結果集中的資料,將完整的資料傳送到connection,生成sqlDataReader賦給sdr。
            //括號中表明當關閉sqlDataReader時,關聯的connection也會關閉。
            using (sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
            {
                //通過提供的sqlDataReader,對錶進行操作
                dt.Load(sdr);
            }
            return dt;
        }
    }
}

結:對於七層登入,一定要理清他的邏輯思路,層與層之間的關係以及程式碼的執行過程,敲完之後多跑幾遍,對於不懂得方法充分利用好ArcObjects幫助文件,裡面的解釋非常詳細(還要感謝帥行的幫助,萬分感謝!)