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. 模型类(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() { }
    }
}

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了;
修改是双击修改信息所在行,该信息就会被读取输出在右侧修改栏(此时右侧添加按钮变为修改按钮),在输出的数据上编辑为修改后数据,点击修改即可完成:
在这里插入图片描述
点击分类管理,会打开零食分类界面,该页面的操作原理同零食管理界面:
在这里插入图片描述


  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值