C#01-三層架構


一、三層架構

1、三層架構是什麼?

通常意義上的三層架構就是將整個業務應用劃分爲:
表現層(UI)、業務邏輯層(BLL)、數據訪問層(DAL)。

區分層次的目的即爲了“高內聚,低耦合”的思想。

表現層(UI):通俗講就是展現給用戶的界面,即用戶在使用一個系統的時候的所見所得。
業務邏輯層(BLL):針對具體問題的操作,也可以說是對數據層的操作,對數據業務邏輯處理。
數據訪問層(DAL):該層所做事務直接操作數據庫,針對數據的增添、刪除、修改、更新、查找等每層之間是一種垂直的關係。

2、優缺點

優點: 分工明確,條理清晰,易於調試,而且具有可擴展性。
缺點: 增加成本。

3、調用關係

DAL、BLL、UI、Model(模型層)、Common(通用層)
調用關係:
DAL層調用Model層,Common層
BLL層調用DAL層、Model層、Common層
UI層調用BLL層、Model層、Common層



在這裏插入圖片描述
例如影院系統零食銷售示例中,我創建瞭如上圖介紹的五個類庫(其中COMMON可以不創建,例子中沒有用到,其餘四個類庫內容在下文展開詳細敘述)
在這裏插入圖片描述

4、開發順序

開發順序:DAL->BLL->UI 翻過來也可以

二、影院系統零食銷售示例

1.創建數據庫

(用的SQL Server)首先創建一個叫 movie 的數據庫,接着創建Snacks(零食)和SnacksType(零食分類)兩張表。

上代碼哈哈哈(也可以手動創建):

USE [movie]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Snacks](
	[SId] [int] IDENTITY(1,1) NOT NULL,
	[STitle] [varchar](50) NOT NULL,
	[SPrice] [decimal](5, 2) NOT NULL,
	[STypeId] [int] NOT NULL,
	[SIsDelete] [int] NOT NULL,
 CONSTRAINT [PK_Snacks] PRIMARY KEY CLUSTERED 
(
	[SId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[SnacksType](
	[SId] [int] IDENTITY(1,1) NOT NULL,
	[STitle] [varchar](10) NOT NULL,
	[SIsDelete] [int] NOT NULL
) ON [PRIMARY]
GO

添加數據:

SET IDENTITY_INSERT [dbo].[Snacks] ON 
INSERT [dbo].[Snacks] ([SId], [STitle], [SPrice], [STypeId], [SIsDelete]) VALUES (1, N'可比克', CAST(15.00 AS Decimal(5, 2)), 1, 0)
INSERT [dbo].[Snacks] ([SId], [STitle], [SPrice], [STypeId], [SIsDelete]) VALUES (2, N'手指餅', CAST(7.50 AS Decimal(5, 2)), 1, 0)
INSERT [dbo].[Snacks] ([SId], [STitle], [SPrice], [STypeId], [SIsDelete]) VALUES (3, N'番茄雞味塊', CAST(7.50 AS Decimal(5, 2)), 1, 0)
INSERT [dbo].[Snacks] ([SId], [STitle], [SPrice], [STypeId], [SIsDelete]) VALUES (4, N'可樂', CAST(4.00 AS Decimal(5, 2)), 2, 0)
INSERT [dbo].[Snacks] ([SId], [STitle], [SPrice], [STypeId], [SIsDelete]) VALUES (5, N'雪碧', CAST(4.00 AS Decimal(5, 2)), 2, 0)
INSERT [dbo].[Snacks] ([SId], [STitle], [SPrice], [STypeId], [SIsDelete]) VALUES (6, N'橙汁', CAST(8.00 AS Decimal(5, 2)), 2, 0)
INSERT [dbo].[Snacks] ([SId], [STitle], [SPrice], [STypeId], [SIsDelete]) VALUES (7, N'西瓜汁', CAST(8.00 AS Decimal(5, 2)), 2, 0)
INSERT [dbo].[Snacks] ([SId], [STitle], [SPrice], [STypeId], [SIsDelete]) VALUES (8, N'奶茶', CAST(8.00 AS Decimal(5, 2)), 2, 0)
INSERT [dbo].[Snacks] ([SId], [STitle], [SPrice], [STypeId], [SIsDelete]) VALUES (9, N'爆米花中份', CAST(10.00 AS Decimal(5, 2)), 3, 0)
INSERT [dbo].[Snacks] ([SId], [STitle], [SPrice], [STypeId], [SIsDelete]) VALUES (10, N'爆米花大份', CAST(15.00 AS Decimal(5, 2)), 3, 0)
SET IDENTITY_INSERT [dbo].[Snacks] OFF
SET IDENTITY_INSERT [dbo].[SnacksType] ON 
INSERT [dbo].[SnacksType] ([SId], [STitle], [SIsDelete]) VALUES (1, N'零食', 0)
INSERT [dbo].[SnacksType] ([SId], [STitle], [SIsDelete]) VALUES (2, N'飲料', 0)
SET IDENTITY_INSERT [dbo].[SnacksType] OFF

2.1 模型類(MODEL)

零食類 Snacks:

namespace MODEL
{
   
    
    public class Snacks
    {
   
    
        //--[SId], [STitle], [SPrice], [STypeId], [SIsDelete]
        public string SId {
   
     get; set; }
        public string STitle {
   
     get; set; }
        public string SPrice {
   
     get; set; }
        public string STypeId {
   
     get; set; }
        public string SIsDelete {
   
     get; set; }
        public string STypeTitle {
   
     get; set; }
        public Snacks() {
   
     }
    }
}

零食分類類 SnacksType:

namespace MODEL
{
   
    
    public class SnacksType
    {
   
    
        //--[SId], [STitle], [SIsDelete]
        public string SId {
   
     get; set; }
        public string STitle {
   
     get; set; }
        public string SIsDelete {
   
     get; set; }
        public SnacksType() {
   
     }
    }
}

2.2 SqlHelper

3.1 數據訪問層(DAL)

數據訪問層里加了一個類SqlHelper,幫助操作數據庫。

SqlHelper:

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

namespace DAL
{
   
    
    public class SqlHelper
    {
   
    
        private static string connStr = "Data Source=.;Initial Catalog=movie;Integrated Security=True";

        //增、刪、改 
        /// <summary>
        /// 執行增、刪、改 的sql語句,返回受影響的行數
        /// </summary>
        /// <param name="sql">要執行的命令</param>
        /// <param name="ps">命令中的參數</param>
        /// <returns>受影響的行數</returns>
        public static int ExecuteNonQuery(string sql, SqlParameter[] ps)
        {
   
    
            using (SqlConnection conn = new SqlConnection(connStr))
            {
   
    
                using (SqlCommand cmd = new SqlCommand(sql, conn))
                {
   
    
                    conn.Open();
                    cmd.Parameters.AddRange(ps);
                    return cmd.ExecuteNonQuery();
                }
            }
        }
        /// <summary>
        /// 執行增、刪、改 的sql語句,返回受影響的行數
        /// </summary>
        /// <param name="sql">要執行的命令</param>
        /// <param name="ps">命令中的參數</param>
        /// <returns>受影響的行數</returns>
        public static int ExecuteNonQuery(string sql)
        {
   
    
            using (SqlConnection conn = new SqlConnection(connStr))
            {
   
    
                using (SqlCommand cmd = new SqlCommand(sql, conn))
                {
   
    
                    conn.Open();
                    return cmd.ExecuteNonQuery();
                }
            }

        }

        //查詢
        public static DataTable getDataTable(string sql, SqlParameter[] ps)
        {
   
    

            using (SqlConnection conn = new SqlConnection(connStr))
            {
   
    
                using (SqlCommand cmd = new SqlCommand(sql, conn))
                {
   
    
                    using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
                    {
   
    
                        DataTable dt = new DataTable();
                        cmd.Parameters.AddRange(ps);
                        sda.Fill(dt);
                        return dt;
                    }
                }
            }
        }
        public static DataTable getDataTable(string sql)
        {
   
    
            using (SqlConnection conn = new SqlConnection(connStr))
            {
   
    
                using (SqlCommand cmd = new SqlCommand(sql, conn))
                {
   
    
                    using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
                    {
   
    
                        DataTable dt = new DataTable();
                        sda.Fill(dt);
                        return dt;
                    }
                }
            }
        }

    }
}

零食 SnacksDAL:

using MODEL;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;

namespace DAL
{
   
    
    public class SnacksDAL
    {
   
    
        //刪除
        public int delete(string sid)
        {
   
    
            string sql = "update Snacks set SIsDelete=1 where SId=@SId";
            SqlParameter[] ps =
                {
   
    
                new SqlParameter("@SId",sid)
            };
            return SqlHelper.ExecuteNonQuery(sql, ps);
        }

        //修改
        public int update(Snacks s)
        {
   
    
            string sql = "update Snacks set STitle=@STitle,Sprice=@Sprice,STypeId=@STypeId where SId=@SId";
            SqlParameter[] ps =
                {
   
    
                new SqlParameter("@Stitle",s.STitle),
                new SqlParameter("@Sprice",s.SPrice),
                new SqlParameter("@STypeId",s.STypeId),
                new SqlParameter("@SId",s.SId)
            };
            return SqlHelper.ExecuteNonQuery(sql, ps);
        }

        //新增
        public int add(Snacks s)
        {
   
    
            string sql = "insert into Snacks(STitle,Sprice,STypeId)values(@STitle,@Sprice,@STypeId)";
            SqlParameter[] ps =
                {
   
    
                new SqlParameter("@STitle",s.STitle),
                new SqlParameter("@Sprice",s.SPrice),
                new SqlParameter("@STypeId",s.STypeId)
            };
            return SqlHelper.ExecuteNonQuery(sql, ps);
        }

        //查詢顯示
        public DataTable getList(Dictionary<string, string> dic)
        {
   
    
            List<SqlParameter> paraList = new List<SqlParameter>();
            string sql = "select s.SId,s.STitle,st.STitle STypeTitle,SPrice from Snacks s,SnacksType st where s.STypeId=st.SId and s.SIsDelete=0";
            if (dic.Count > 0)
            {
   
    
                foreach (KeyValuePair<string, string> kv in dic)
                {
   
    
                    sql += " and s." + kv.Key + " like @" + kv.Key;
                    string pname = "@" + kv.Key;
                    string pvalue = "%" + kv.Value + "%";
                    paraList.Add(new SqlParameter(pname, pvalue));
                }
            }

            return SqlHelper.getDataTable(sql, paraList.ToArray());
        }
    }
}

零食分類 SnacksTypeDAL:

using MODEL;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;

namespace DAL
{
   
    
    public class SnacksTypeDAL
    {
   
    
        //刪除
        public int delete(string sid)
        {
   
    
            string sql = "delete from SnacksType where SId=@SId";
            SqlParameter[] ps =
                {
   
    
                new SqlParameter("@SId",sid)
            };
            return SqlHelper.ExecuteNonQuery(sql, ps);
        }

        //修改
        public int update(SnacksType s)
        {
   
    
            string sql = "update SnacksType set STitle=@STitle where SId=@SId";
            SqlParameter[] ps =
                {
   
    
                new SqlParameter("@STitle",s.STitle),
                new SqlParameter("@SId",s.SId)
            };
            return SqlHelper.ExecuteNonQuery(sql, ps);
        }

        //添加
        public int add(SnacksType s)
        {
   
    
            string sql = "insert into SnacksType(STitle)values(@STitle)";
            SqlParameter[] ps =
                {
   
    
                new SqlParameter("@STitle",s.STitle)
            };
            return SqlHelper.ExecuteNonQuery(sql, ps);

        }

        //查詢顯示
        public DataTable getList()
        {
   
    
            string sql = "select SId,STitle from SnacksType";
            return SqlHelper.getDataTable(sql);
        }
    }
}

3.2 業務邏輯層(BLL)

零食 SnacksBLL:

using DAL;
using MODEL;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

namespace BLL
{
   
    
    public class SnacksBLL
    {
   
    
        SnacksDAL dal = new SnacksDAL();

        //刪除
        public bool delete(string sid)
        {
   
    
            return dal.delete(sid) > 0;
        }

        //修改
        public bool update(Snacks s)
        {
   
    
            return dal.update(s) > 0;
        }

        //添加
        public bool add(Snacks s)
        {
   
    
            return dal.add(s) > 0;
        }

        //查詢顯示
        public List<Snacks> getList(Dictionary<string, string> dic)
        {
   
    
            List<Snacks> list = new List<Snacks>();
            DataTable dt = dal.getList(dic);
            foreach (DataRow row in dt.Rows)
            {
   
    
                Snacks s = new Snacks();
                s.SId = row["SId"].ToString();
                s.STitle = row["STitle"].ToString();
                s.SPrice = row["SPrice"].ToString();
                s.STypeId = row["STypeTitle"].ToString();
                list.Add(s);
            }
            return list;
        }
    }
}

零食分類 SnacksTypeBLL:

using DAL;
using MODEL;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

namespace BLL
{
   
    
    public class SnacksTypeBLL
    {
   
    
        SnacksTypeDAL dal = new SnacksTypeDAL();
        //刪除
        public bool delete(string sid)
        {
   
    
            return dal.delete(sid) > 0;
        }

        //修改
        public bool update(SnacksType s)
        {
   
    
            return dal.update(s) > 0;
        }

        //添加
        public bool add(SnacksType s)
        {
   
    
            return dal.add(s) > 0;
        }

        //查詢顯示
        public List<SnacksType> getList()
        {
   
    
            List<SnacksType> list = new List<SnacksType>();
            DataTable dt = dal.getList();
            foreach (DataRow row in dt.Rows)
            {
   
    
                SnacksType t = new SnacksType();
                t.SId = row["SId"].ToString();
                t.STitle = row["STitle"].ToString();
                list.Add(t);
            }
            return list;
        }
    }
}

3.3表現層(UI)

這是我畫的零食界面:
在這裏插入圖片描述
事件代碼:

using BLL;
using MODEL;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace UI
{
   
    
    public partial class FormSnacks : Form
    {
   
    
        public FormSnacks()
        {
   
    
            InitializeComponent();
        }

        SnacksBLL bll = new SnacksBLL();

        //拼接模糊查詢條件
        private void loadList()
        {
   
    
            Dictionary<string, string> dic = new Dictionary<string, string>();
            string titleSearch = txtTitleSearch.Text.Trim();
            string typesearch = ddlTypeSearch.SelectedValue.ToString();
            //MessageBox.Show(typesearch);
            //創建泛型鍵值對集合、用於存儲SQL語句中模糊查詢的條件
            if (txtTitleSearch.Text != "")
            {
   
    
                dic.Add("STitle", txtTitleSearch.Text);
            }
            if (typesearch != "0")
            {
   
    
                dic.Add("STypeId", typesearch);
            }

            dgvList.AutoGenerateColumns = false;
            dgvList.DataSource = bll.getList(dic);
        }

        //分類搜索下拉框
        private void loadSearchTypeList()
        {
   
    
            SnacksTypeBLL stbll = new SnacksTypeBLL();
            List<SnacksType> list = stbll.getList();

            SnacksType st = new SnacksType();
            st.SId = "0";
            st.STitle = "全部";
            // list.Add(st);
            list.Insert(0, st);

            //綁定數據
            ddlTypeSearch.DisplayMember = "STitle";
            ddlTypeSearch.ValueMember = "SId";
            ddlTypeSearch.DataSource = list;
        }

        //增加/修改分類下拉框
        private void loadAddTypeList()
        {
   
    
            SnacksTypeBLL stbll = new SnacksTypeBLL();
            List<SnacksType> list = stbll.getList();
            SnacksType st = new SnacksType();
            st.SId = "0";
            st.STitle = "全部";
            // list.Add(st);
            list.Insert(0, st);

            //SId,STitle
            ddlTypeAdd.DisplayMember = "STitle";
            ddlTypeAdd.ValueMember = "SId";
            ddlTypeAdd.DataSource = list;
        }

        private void FormSnacks_Load(object sender, EventArgs e)
        {
   
    
            loadSearchTypeList();
            loadAddTypeList();
            loadList();
        }

        private void DgvList_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
   
    
            DataGridViewRow rows = dgvList.SelectedRows[0];
            txtId.Text = rows.Cells["SId"].Value.ToString();
            txtTitleSave.Text = rows.Cells["STitle"].Value.ToString();
            txtPrice.Text = rows.Cells["SPrice"].Value.ToString();
            txtId.Text = rows.Cells["SId"].Value.ToString();
            ddlTypeAdd.Text = rows.Cells["STypeId"].Value.ToString();
            btnSave.Text = "修改";
        }

        private void BtnSave_Click(object sender, EventArgs e)
        {
   
    
            string str = txtId.Text.Trim();
            Snacks s = new Snacks();
            s.SId = txtId.Text;
            s.STitle = txtTitleSave.Text;
            s.SPrice = txtPrice.Text;
            s.STypeId = ddlTypeAdd.SelectedValue.ToString();
            s.STypeTitle = ddlTypeAdd.Text;
            if (str.Equals("添加時無編號"))
            {
   
    
                if (bll.add(s))
                {
   
    
                    MessageBox.Show("添加成功!");
                    loadList();
                }
                else
                {
   
    
                    MessageBox.Show("添加失敗!");
                }
            }
            else
            {
   
    
                if (bll.update(s))
                {
   
    
                    MessageBox.Show("修改成功!");
                    loadList();
                }
                else
                {
   
    
                    MessageBox.Show("修改失敗!");
                }
            }
        }

        private void BtnCancel_Click(object sender, EventArgs e)
        {
   
    
            txtId.Text = "添加時無編號";
            txtTitleSave.Text = "";
            txtPrice.Text = "";
            ddlTypeAdd.SelectedIndex = 0;
            btnSave.Text = "添加";
        }

        private void BtnRemove_Click(object sender, EventArgs e)
        {
   
    
            DataGridViewRow rows = dgvList.SelectedRows[0];
            string sid = rows.Cells["SId"].Value.ToString();
            if (bll.delete(sid))
            {
   
    
                MessageBox.Show("刪除成功!");
                loadList();
            }
            else
            {
   
    
                MessageBox.Show("刪除失敗!");
            }
        }

        private void TxtTitleSearch_TextChanged(object sender, EventArgs e)
        {
   
    
            loadList();
        }

        private void DdlTypeSearch_SelectedIndexChanged(object sender, EventArgs e)
        {
   
    
            loadList();
        }

        private void BtnSearchAll_Click(object sender, EventArgs e)
        {
   
    
            txtTitleSearch.Clear();
            ddlTypeSearch.Text = "全部";
        }

        private void BtnAddType_Click(object sender, EventArgs e)
        {
   
    
            FormSnacksType fst = new FormSnacksType();
            fst.StartPosition = FormStartPosition.CenterScreen;
            if (fst.ShowDialog() == DialogResult.Yes)
            {
   
    
                loadAddTypeList();
                loadSearchTypeList();
            }
        }
    }
}

點擊首頁的“分類管理“按鈕會打開零食分類頁面(這裏我給這個按鈕起名叫btnAddType,,命名不嚴謹了),其實零食分類管理和零食管理的原理都一樣都是增刪查改。
零食分類界面:
在這裏插入圖片描述
事件代碼:


using BLL;
using MODEL;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace UI
{
   
    
    public partial class FormSnacksType : Form
    {
   
    
        public FormSnacksType()
        {
   
    
            InitializeComponent();
        }

        SnacksTypeBLL bll = new SnacksTypeBLL();
        private DialogResult dr = DialogResult.No;

        //刷新
        private void loadList()
        {
   
    
            List<SnacksType> list = bll.getList();
            dgvList.AutoGenerateColumns = false;
            dgvList.DataSource = list;
        }

        private void FormSnacksType_Load(object sender, EventArgs e)
        {
   
    
            loadList();
        }

        private void BtnSave_Click(object sender, EventArgs e)
        {
   
    
            string str = txtId.Text.Trim();
            if (str.Equals("添加時無編號"))
            {
   
    
                SnacksType s = new SnacksType();
                s.STitle = txtTitle.Text;
                if (bll.add(s))
                {
   
    
                    MessageBox.Show("添加成功!");
                    loadList();
                    dr = DialogResult.Yes;
                }
                else
                {
   
    
                    MessageBox.Show("添加失敗!");
                }
            }
            else
            {
   
    
                SnacksType s = new SnacksType();
                s.SId = txtId.Text;
                s.STitle = txtTitle.Text;
                if (bll.update(s))
                {
   
    
                    MessageBox.Show("修改成功!");
                    loadList();
                    dr = DialogResult.Yes;
                }
                else
                {
   
    
                    MessageBox.Show("修改失敗!");
                }
            }
        }

        private void DgvList_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
   
    
            DataGridViewRow rows = dgvList.SelectedRows[0];
            txtId.Text = rows.Cells["SId"].Value.ToString();
            txtTitle.Text = rows.Cells["STitle"].Value.ToString();
            btnSave.Text = "修改";
        }

        private void BtnCancel_Click(object sender, EventArgs e)
        {
   
    
            txtId.Text = "添加時無編號";
            txtTitle.Text = "";
            btnSave.Text = "添加";
        }

        private void BtnRemove_Click(object sender, EventArgs e)
        {
   
    
            DataGridViewRow row = dgvList.SelectedRows[0];
            string sid = row.Cells["SId"].Value.ToString();
            if (bll.delete(sid))
            {
   
    
                MessageBox.Show("刪除成功!");
                loadList();
                dr = DialogResult.Yes;
            }
            else
            {
   
    
                MessageBox.Show("刪除失敗!");
            }
        }

        private void FormSnacksType_FormClosing(object sender, FormClosingEventArgs e)
        {
   
    
            this.DialogResult = dr;
        }
    }
}

三、運行結果

在這裏插入圖片描述
運行要注意把Program中的運行窗體改爲我們需要的,比如這裏是FormSnacks();

數據顯示ok:
在這裏插入圖片描述
分類查找模糊查找ok:
在這裏插入圖片描述
添加數據就直接在右側輸入相關信息,點擊添加就ok了;
刪除數據選中數據所在行,點擊刪除按鈕就ok了;
修改是雙擊修改信息所在行,該信息就會被讀取輸出在右側修改欄(此時右側添加按鈕變爲修改按鈕),在輸出的數據上編輯爲修改後數據,點擊修改即可完成:
在這裏插入圖片描述
點擊分類管理,會打開零食分類界面,該頁面的操作原理同零食管理界面:
在這裏插入圖片描述









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章