c#利用三層架構做一個簡單的登錄窗體


就個人而言,三層架構有點難理解,不知道該如何下手,各層與各層之間怎么調用

最近一直在研究三層架構,經過網上學習與多方打聽寫一下自己的心得。有不足之處,可以評論和私聊探討

言歸正傳:

三層架構(3-tier architecture) 通常意義上的三層架構就是將整個業務應用划分為:界面層(User Interface layer)、業務邏輯層(Business Logic Layer)、數據訪問層(Data access layer)。區分層次的目的即為了"高內聚低耦合"的思想。在軟件體系架構設計中,分層式結構是最常見,也是最重要的一種結構。微軟推薦的分層式結構一般分為三層,從下至上分別為:數據訪問層、業務邏輯層(又或稱為領域層)、表示層。

三層體系的應用程序將業務規則、數據訪問、合法性校驗等工作放到了中間層進行處理。通常情況下,客戶端不直接與數據庫進行交互,而是通過COM/DCOM通訊與中間層建立連接,再經由中間層與數據庫進行交互。

UI層:即表示層,就是展現給用戶看到的界面

BLL:即業務邏輯層,就是實現功能的,用來寫方法及其調用

DAL:即數據訪問層,也就是說,是對數據庫的操作,而不是數據,具體為業務邏輯層或表示層提供數據服務。說白了就是寫sql語句的;主要是存放對數據類的訪問,即對數據庫的添加、刪除、修改、更新等基本操作

除此三層外,聰明的人一定就還會說中間還有一個model(模型層)作為承載數據的媒介,供上面三個層引用。用來存儲實體類的,所以model實體類也很重要,

model:實體類庫,主要存放數據庫中的表字段

引用順序為UI引用BLL;BLL引用DAL;也可以間接引用

案例分析:

我們以一個登錄窗體作為案例

首先在數據庫建一張賬號用戶表,並填寫部分數據,用來測試

如圖

 

方案目錄結構 

就個人而言還是從UI層開寫更好一點,因為UI層能直觀的看出你想實現什么功能效果,以便於下層該怎么下手

1.UI層

 

UI層做好,接下來最好做model實體類,實體類庫(Model),主要存放數據庫中的表字段。

后台代碼:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 登錄
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        //實例化model層中 userInfo類用於傳遞數據  
        Model.userInfo m_userInfo = new Model.userInfo();

        //實例化BAL層中 userAccess方法銜接用戶輸入與數據庫匹配  
        BAL.userBLL b_userAccess = new BAL.userBLL();
        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            //將用戶輸入的賬號密碼 賦值給userInfo類 username、psw屬性  
            m_userInfo.username = textBox1.Text.Trim().ToString();
            m_userInfo.psw = textBox2.Text.Trim().ToString();

            //如果BLL層中 useLogin調用返回記錄條數 大於1 則賬號密碼正確  
            if (b_userAccess.userLogin(m_userInfo) > 0)
            {
                MessageBox.Show("登錄成功");
            }
            else
            {
                MessageBox.Show("登錄失敗");
            }
        }
    }
}

 

2.MODEL模型層

model層其實就相當於一個中轉站,用來存儲用到的數據,貫穿三層,數據的賦值及提取

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApp4.MODEL
{
    class userInfo //想創建一個用戶實體類
    {
      //用get;set方法
      public string username { get; set; }
        public string password { get; set; }
    }
}

 

model實體類做好后接下來就可以寫DAL層了,DAL就是書寫sql語句操作數據庫,(就拿登錄窗體來說,我們在登錄時要輸入賬號和密碼,點擊登錄時就要與數據庫里的數據進行對比,只有驗證一致才能登陸成功。這時就要書寫sql語句取出數據庫里的數據與你在輸入框輸入的數據進行對比)

在寫DAL層時要寫一個SQLhelper幫助類(六面提供了很多方法與對象,極大的方便了開發人員的開發效率;其實一個sqlhelper幫助類可以放在任何地方調用,那小編就給大家一唄)

 

  1 using System;
  2 using System.Data;
  3 using System.Collections;
  4 using System.Configuration; //記得這個asp默認沒引用,你要去添加引用的程序集里引用進來
  5 using System.Linq;
  6 using System.Web;
  7 using System.Xml.Linq;
  8 using System.Data.SqlClient;
  9 using System.Collections.Generic;
 10 
 11 namespace UMS.DbHelper
 12 {
 13     /// <summary>
 14     /// SQL數據庫操作類
 15     /// </summary>
 16     public class SQLHelper
 17     {
 18         private string strConn;
 19         private SqlConnection sqlConn = null;
 20 
 21         public SQLHelper()
 22         {
 23             strConn = ConfigurationManager.ConnectionStrings["UserData"].ConnectionString;
 24             sqlConn = new SqlConnection(strConn);
 25        
 26         }
 27 
 28         /// <summary>
 29         /// 打開數據庫連接
 30         /// </summary>
 31         private void OpenConn()
 32         {
 33             if (sqlConn != null && sqlConn.State == ConnectionState.Closed)
 34             {
 35                 sqlConn.Open();
 36             }
 37         }
 38 
 39         /// <summary>
 40         /// 關閉數據庫連接
 41         /// </summary>
 42         private void CloseConn()
 43         {
 44             if (sqlConn != null && sqlConn.State == ConnectionState.Open)
 45             {
 46                 sqlConn.Close();
 47             }
 48         }
 49         /// <summary>
 50         /// 構造操作命令
 51         /// </summary>
 52         /// <param name="cmdText">帶參命令</param>
 53         /// <param name="param">參數數組</param>
 54         /// <param name="values">參數值數組</param>
 55         /// <returns></returns>
 56         private SqlCommand CreateCommand(string cmdText, string[] param, object [] values)
 57         {
 58             SqlCommand myCmd = new SqlCommand(cmdText,sqlConn);
 59             for (int i = 0; i < param.Length; i++)
 60             {
 61                 myCmd.Parameters.AddWithValue(param[i],values[i]);
 62             }
 63             return myCmd;
 64         }
 65         /// <summary>
 66         /// 根據SQL指令返回相應查詢閱讀器,在閱讀器使用完后請及時關閉
 67         /// </summary>
 68         /// <param name="cmdText">查詢語句</param>
 69         /// <param name="param">參數列表,無參可設置為null</param>
 70         /// <param name="values">參數值列表,只有當參數不為空時有效</param>
 71         /// <returns></returns>
 72         public SqlDataReader ExecuteReader(string cmdText,string [] param,object [] values)
 73         {
 74             OpenConn();
 75             SqlCommand myCmd;
 76             if (param != null)
 77             {
 78                 myCmd = this.CreateCommand(cmdText, param, values);
 79             }
 80             else
 81             {
 82                 myCmd = new SqlCommand(cmdText,sqlConn);
 83             }
 84             return myCmd.ExecuteReader(CommandBehavior.CloseConnection);
 85         }
 86 
 87         /// <summary>
 88         /// 根據存儲過程返回相應查詢閱讀器,在閱讀器使用完后請及時關閉
 89         /// </summary>
 90         /// <param name="cmdText">存儲過程名</param>
 91         /// <param name="parms">參數列表</param>
 92         /// <returns></returns>
 93         public SqlDataReader ExecuteReaderBySP(string cmdText, SqlParameter[] parms)
 94         {
 95             OpenConn();
 96             SqlCommand myCmd = new SqlCommand(cmdText, sqlConn);
 97             myCmd.CommandType = CommandType.StoredProcedure;
 98             if (parms != null)
 99             {
100                 myCmd.Parameters.AddRange(parms);
101             }
102             return myCmd.ExecuteReader(CommandBehavior.CloseConnection);
103         }
104 
105         /// <summary>
106         /// 根據SQL指令返回受影響行數,主要用於數據庫的更新、插入、刪除等操作
107         /// </summary>
108         /// <param name="cmdText">sql命令語句</param>
109         /// <param name="param">參數數組,若沒有參數可以設置為空</param>
110         /// <param name="values">參數值數組,只有當param不為空時有效</param>
111         /// <returns></returns>
112         public int ExecuteNoneQuery(string cmdText, string[] param, object[] values)
113         {
114             OpenConn();
115             SqlCommand myCmd;
116             if (param != null)
117             {
118                 myCmd = this.CreateCommand(cmdText, param, values);
119             }
120             else
121             {
122                 myCmd = new SqlCommand(cmdText,sqlConn);
123             }
124             try
125             {
126                 return myCmd.ExecuteNonQuery();
127             }
128             catch (Exception ex)
129             {
130                 throw ex;
131             }
132             finally
133             {
134                 CloseConn();
135             }
136         }
137 
138         /// <summary>
139         /// 根據SQL指令返回第一行第一列結果
140         /// </summary>
141         /// <param name="cmdText">sql命令語句</param>
142         /// <param name="param">參數數組,若沒有參數可以設置為空</param>
143         /// <param name="values">參數值數組,只有當param不為空時有效</param>
144         /// <returns></returns>
145         public object ExecuteScalar(string cmdText, string[] param, object[] values)
146         {
147             OpenConn();
148             SqlCommand myCmd;
149             if (param != null)
150             {
151                 myCmd = this.CreateCommand(cmdText, param, values);
152             }
153             else
154             {
155                 myCmd = new SqlCommand(cmdText,sqlConn);
156             }
157             try
158             {
159                 return myCmd.ExecuteScalar();
160             }
161             catch (Exception ex)
162             {
163                 throw ex;
164             }
165             finally
166             {
167                 CloseConn();
168             }
169         }
170         /// <summary>
171         /// 帶事務執行存儲過程,該方法主要用於執行用於數據維護類的存儲過程執行
172         /// </summary>
173         /// <param name="cmdText">存儲過程名稱</param>
174         /// <param name="parms">SQL參數數組</param>
175         public int  ExecuteNoneQueryBySP(string cmdText, SqlParameter[] parms)
176         {
177             OpenConn();
178             SqlTransaction tran = sqlConn.BeginTransaction();
179             SqlCommand myCmd = new SqlCommand(cmdText, sqlConn);
180             myCmd.CommandType = CommandType.StoredProcedure;
181             if (parms != null)
182             {
183                 myCmd.Parameters.AddRange(parms);
184             }
185             myCmd.Transaction = tran;
186             try
187             {
188                 int result=myCmd.ExecuteNonQuery();
189                 tran.Commit();
190                 return result;
191             }
192             catch (Exception ex)
193             {
194                 tran.Rollback();
195                 throw ex;
196             }
197             finally
198             {
199                 CloseConn();
200             }
201         }
202         /// <summary>
203         /// 根據命令語句返回數據集
204         /// </summary>
205         /// <param name="cmdText">命令語句</param>
206         /// <param name="param">參數數組,若沒有參數可以設置為空</param>
207         /// <param name="values">參數值數組,只有當param不為空時有效</param>
208         /// <returns></returns>
209         public DataSet FillDataSet(string cmdText, string[] param, object[] values)
210         {
211             OpenConn();
212             SqlCommand myCmd;
213             if (param != null)
214             {
215                 myCmd = this.CreateCommand(cmdText, param, values);
216             }
217             else
218             {
219                 myCmd = new SqlCommand(cmdText,sqlConn);
220             }
221             SqlDataAdapter myAdp = new SqlDataAdapter(myCmd);
222             DataSet ds = new DataSet();
223             try
224             {
225                 myAdp.Fill(ds);
226                 return ds;
227             }
228             catch (Exception ex)
229             {
230                 throw ex;
231             }
232             finally
233             {
234                 CloseConn();
235             }
236         }
237 
238         /// <summary>
239         /// 執行特定存儲過程並返回查詢后的數據結果,該方法用於執行查詢類的存儲過程
240         /// </summary>
241         /// <param name="cmdText">存儲過程名</param>
242         /// <param name="parms">SQL參數數組,若沒有參數可以設置為空</param>
243         /// <returns></returns>
244         public DataSet FillDataSetBySP(string cmdText, SqlParameter[] parms)
245         {
246             OpenConn();
247             SqlCommand myCmd = new SqlCommand(cmdText, sqlConn);
248             myCmd.CommandType = CommandType.StoredProcedure;
249             if (parms != null)
250             {
251                 myCmd.Parameters.AddRange(parms);
252             }
253             SqlDataAdapter myAdp = new SqlDataAdapter(myCmd);
254             DataSet ds = new DataSet();
255             try
256             {
257                 myAdp.Fill(ds);
258                 return ds;
259             }
260             catch (Exception ex)
261             {
262                 throw ex;
263             }
264             finally
265             {
266                 CloseConn();
267             }
268         }
269         /// <summary>
270         /// 執行存儲過程返回輸出參數
271         /// </summary>
272         /// <param name="cmdText">存儲過程名</param>
273         /// <param name="parms">參數數組</param>
274         /// <returns>包含所有輸出值的ArrayList</returns>
275         public ArrayList ExecuteSp(string cmdText, SqlParameter[] parms)
276         {
277             OpenConn();
278             SqlCommand myCmd = new SqlCommand(cmdText, sqlConn);
279             myCmd.CommandType = CommandType.StoredProcedure;
280             if (parms != null)
281             {
282                 myCmd.Parameters.AddRange(parms);
283             }
284             try
285             {
286                 myCmd.ExecuteNonQuery();
287                 ArrayList al = new ArrayList();
288                 for (int i = 0; i < parms.Length; i++)
289                 {
290                     if (parms[i].Direction == ParameterDirection.Output)
291                     {
292                         al.Add(parms[i]);
293                     }
294                 }
295                 return al;
296             }
297             catch (Exception ex)
298             {
299                 throw ex;
300             }
301             finally
302             {
303                 CloseConn();
304             }
305         }
306 
307         #region 批處理操作
308         /// <summary>
309         /// 批量數據導入操作
310         /// </summary>
311         /// <param name="dt">要批量導入的數據表</param>
312         /// <param name="destTableName">目標表名</param>
313         /// <param name="columnMappings">列映射集合</param>
314         public void BulkInsert(DataTable dt, string destTableName, List<SqlBulkCopyColumnMapping> columnMappings)
315         {
316             SqlBulkCopy bulkCopy = new SqlBulkCopy(this.sqlConn);
317             bulkCopy.DestinationTableName = destTableName;
318             bulkCopy.BatchSize = dt.Rows.Count;
319             foreach (SqlBulkCopyColumnMapping map in columnMappings)
320             {
321                 bulkCopy.ColumnMappings.Add(map);
322             }
323             try
324             {
325                 OpenConn();
326                 bulkCopy.WriteToServer(dt);
327             }
328             catch (Exception ex)
329             {
330                 throw ex;
331             }
332             finally
333             {
334                 this.CloseConn();
335                 bulkCopy.Close();
336             }
337         }
338         #endregion
339     }
340 }
View Code

 

 

類里邊不是有個數據庫訪問方法,那里是在配置文件里配置了數據庫連接字符串,所以就沒有在方法里寫連接字符串

例如

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
      
    </startup>
  <connectionStrings>
    <add name="UserData" connectionString="Data Source=.;Initial Catalog=賬號表;User ID=sa;Password=密碼"/>
  </connectionStrings>
</configuration>

 

 

SqlHelper

私有方法有四個,AssignParameterValues方法有一個重載:

AttachParameters:添加參數數組到指定的SqlCommand中 
AssignParameterValues:為SqlParameters(參數)數組賦值 
PrepareCommand:用於對SqlCommand(命令)的屬性(如連接、事務環境等)進行初始化。

公有方法有十三個:這當中每個查詢數據庫的方法用到了大量的重載,每個方法用到了八個左右的重載。

ExecuteNonQuery

此方法用於執行不返回任何行或值的命令。這些命令通常用於執行數據庫更新,但也可用於返回存儲過程的輸出參數。

ExecuteDataset

此方法返回DataSet對象,該對象包含由某一命令返回的結果集。

ExecuteReader

此方法用於返回SqlDataReader對象,該對象包含由某一命令返回的結果集。

ExecuteScalar

此方法返回一個值。該值始終是該命令返回的第一行的第一列。

ExecuteXmlReader

此方法返回 FOR XML 查詢的 XML 片段。

FillDataset

此方法向DataSet填充數據。

UpdateDataset

此方法用於執行向DataSet增、刪、改的命令。

CreateCommand

此方法用於創建SqlCommand。

 

3.DAL層

建好第一步就先把sqlhelper類和model實體類引進來(以創建對象的方式)

 我這里只寫了登錄時用到的,別的就要靠你自己摸索了

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DAL
{
    public class userDAL

    {
        //實例化DBbase 對象  
        DBbase db = new DBbase();

        //用戶登錄的方法  
        public int userLogin(string name, string psw)
        {
            string strsql = "select * from users where username = '" + name + "' and password = '" + psw + "'";
            return db.returnRowCount(strsql);
        }
    }
}
View Code

 登錄的sqlhelper類,在這里叫DBbase

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;

namespace DAL
{
    public class DBbase
    {
        //讀取配置文件 連接數據庫語句  
        public static string strCon = System.Configuration.ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString;
        //public static string strCon = "Data Source=.;Initial Catalog=threeLayer;Persist Security Info=True;User ID=sa;Password=123";  

        //實例化連接對象 con  
        SqlConnection con = new SqlConnection(strCon);

        //檢測連接是否打開  
        public void chkConnection()
        {
            if (this.con.State == ConnectionState.Closed)
            {
                this.con.Open();
            }
        }

        //執行語句,返回該語句查詢的數據行的總行數  
        public int returnRowCount(string strSQL)
        {
            chkConnection();
            try
            {
                SqlDataAdapter da = new SqlDataAdapter(strSQL, con);
                DataSet ds = new DataSet();
                da.Fill(ds);
                return ds.Tables[0].Rows.Count;
            }
            catch
            {
                return 0;
            }
        }
    }
}

4.BLL層 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BAL
{
    public class userBLL
    {
        DAL.userDAL d_userAccess = new DAL.userDAL();
        public int userLogin(Model.userInfo m_userInfo)//把model層的值傳過來進行比對
        {
            return d_userAccess.userLogin(m_userInfo.username, m_userInfo.psw);//如果有返回值則登錄成功
        }
    }
}

 

 

 

到這里就大功告成了,登錄效果

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM