C#使用三层架构开发Winform的详细案例
三层架构将整个业务应用划分为:
- (1)界面UI层
- (2)业务逻辑层
- (3)数据访问层
对于复杂的系统分层可以让结构更加清晰,模块更加独立,便于维护。
各层的任务:
- (1)数据访问层:负责数据库的操作。
- (2)业务逻辑层:实现功能模块的业务逻辑。
- (3)界面UI层:绘制界面,以及负责界面相关代码。
- (4)实体类:将数据库中的表转化为面向对象思想中的类。
一、案例需求
使用三层架构实现学生管理:
(1)专业下拉框绑定专业表数据,网格控件绑定学生数据,并且点击"搜索"按钮可以多条件组合查询。
(2)选中某一行,右键可以弹出"删除"菜单,点击"删除"菜单可以删除学生数据。
(3)点击"新增"按钮,弹出新增窗体,在此窗体中完成学生的新增操作。
(4)选中某一行,点击"编辑"按钮,弹出编辑窗体,在此窗体中完成数据的修改。
备注:其中性别的单选框,以及爱好的多选框分别用两个Pannel容器包含。
数据库准备:
--专业 create table ProfessionInfo ( ProfessionID int primary key identity(1,1), --专业编号 ProfessionName varchar(50) not null unique --专业名称 ) --学生 create table StudentInfo ( StuID varchar(20) primary key, --学生学号 StuName varchar(50) not null, --学生姓名 StuAge int not null check(StuAge > 0 and StuAge < 130), --学生年龄 StuSex char(2) not null check(StuSex in('男','女')), --学生性别 StuHobby nvarchar(100), --爱好 ProfessionID int not null references ProfessionInfo(ProfessionID), --所属专业编号 ) --添加专业信息 insert into ProfessionInfo(ProfessionName) values('电子竞技') insert into ProfessionInfo(ProfessionName) values('软件开发') insert into ProfessionInfo(ProfessionName) values('医疗护理') --插入学生信息 insert into StudentInfo(StuID,StuName,StuAge,StuSex,StuHobby,ProfessionID) values('001','刘备',18,'男','',1) insert into StudentInfo(StuID,StuName,StuAge,StuSex,StuHobby,ProfessionID) values('002','关羽',20,'男','',2) insert into StudentInfo(StuID,StuName,StuAge,StuSex,StuHobby,ProfessionID) values('003','张飞',19,'男','',2) insert into StudentInfo(StuID,StuName,StuAge,StuSex,StuHobby,ProfessionID) values('004','孙尚香',17,'女','',3)
二、项目结构
(1)创建一个空白解决方案。
(2)在解决方案中创建类库项目MyEntity代表"实体类"。
(3)在解决方案中创建类库项目MyDAL代表"数据访问层"。
(4)在解决方案中创建类库项目MyBLL代表"业务逻辑层"。
(5)在解决方案中创建Windows窗体应用程序MyUI代表"界面UI层"。
三、实体类编写
在MyEntity项目中添加两个实体类,实体类代码如下:
ProfessionInfoEntity:
public class ProfessionInfoEntity { public ProfessionInfoEntity() { this.ProfessionID = 0; this.ProfessionName = ""; } public int ProfessionID { get; set; } //专业编号 public string ProfessionName { get; set; }//专业名称 }
StudentInfoEntiy:
public class StudentInfoEntiy { public StudentInfoEntiy() { this.StuID = ""; this.StuName = ""; this.StuAge = 0; this.StuSex = ""; this.StuHobby = ""; this.ProfessionID = 0; this.ProfessionName = ""; } public string StuID { get; set; } //学生学号 public string StuName { get; set; } //学生姓名 public int StuAge { get; set; } //学生年龄 public string StuSex { get; set; } //学生性别 public string StuHobby { get; set; } //学生爱好 public int ProfessionID { get; set; } //学生所属专业编号 public string ProfessionName { get; set; } //学生所属专业名称 }
四、数据访问层编写
(1)由于数据访问层需要使用实体类,所以需要添加实体类的引用。
即在MyDAL项目上右键-->添加-->引用-->项目,在项目中勾选MyEntity项目。
(2)将之前封装好的DBHelper文件复制到MyDAL项目中,并通过添加现有项,将DBHelper加入项目。
(3)在MyDAL项目中添加两个类,类代码如下:
ProfessionInfoDAL:
public class ProfessionInfoDAL { #region 新增 public int Add(ProfessionInfoEntity entity) { string sql = "insert into ProfessionInfo(professionName) values(@professionName)"; DBHelper.PrepareSql(sql); DBHelper.SetParameter("ProfessionName",entity.ProfessionName); return DBHelper.ExecNonQuery(); } #endregion #region 删除 public int Delete(int id) { string sql = "delete from ProfessionInfo where ProfessionID=@ProfessionID"; DBHelper.PrepareSql(sql); DBHelper.SetParameter("ProfessionID", id); return DBHelper.ExecNonQuery(); } #endregion #region 修改 public int Update(ProfessionInfoEntity entity) { string sql = "update ProfessionInfo set professionName=@professionName where ProfessionID=@ProfessionID"; DBHelper.PrepareSql(sql); DBHelper.SetParameter("professionName", entity.ProfessionName); DBHelper.SetParameter("ProfessionID", entity.ProfessionID); return DBHelper.ExecNonQuery(); } #endregion #region 列表 public List<ProfessionInfoEntity> List() { string sql = "select * from ProfessionInfo"; DataTable dt = new DataTable(); DBHelper.PrepareSql(sql); dt = DBHelper.ExecQuery(); List<ProfessionInfoEntity> list = new List<ProfessionInfoEntity>(); foreach (DataRow item in dt.Rows) { ProfessionInfoEntity entity = new ProfessionInfoEntity(); entity.ProfessionID = int.Parse(item["ProfessionID"].ToString()); entity.ProfessionName = item["ProfessionName"].ToString(); list.Add(entity); } return list; } #endregion #region 详情 public ProfessionInfoEntity Detail(int id) { string sql = "select * from ProfessionInfo where ProfessionID=@ProfessionID"; DataTable dt = new DataTable(); DBHelper.PrepareSql(sql); DBHelper.SetParameter("ProfessionID", id); dt = DBHelper.ExecQuery(); if (dt.Rows.Count == 0) return null; ProfessionInfoEntity entity = new ProfessionInfoEntity(); entity.ProfessionID = int.Parse(dt.Rows[0]["ProfessionID"].ToString()); entity.ProfessionName = dt.Rows[0]["ProfessionName"].ToString(); return entity; } #endregion }
StudentInfoDAL:
public class StudentInfoDAL { #region 新增 public int Add(StudentInfoEntiy entity) { string sql = "insert into StudentInfo(StuID,StuName,StuAge,StuSex,StuHobby,ProfessionID) values(@StuID,@StuName,@StuAge,@StuSex,@StuHobby,@ProfessionID)"; DBHelper.PrepareSql(sql); DBHelper.SetParameter("StuID", entity.StuID); DBHelper.SetParameter("StuName", entity.StuName); DBHelper.SetParameter("StuAge", entity.StuAge); DBHelper.SetParameter("StuSex", entity.StuSex); DBHelper.SetParameter("StuHobby", entity.StuHobby); DBHelper.SetParameter("ProfessionID", entity.ProfessionID); return DBHelper.ExecNonQuery(); } #endregion #region 删除 public int Delete(string id) { string sql = "delete from StudentInfo where StuID=@StuID"; DBHelper.PrepareSql(sql); DBHelper.SetParameter("StuID", id); return DBHelper.ExecNonQuery(); } #endregion #region 修改 public int Update(StudentInfoEntiy entity) { string sql = "update StudentInfo set StuName=@StuName,StuAge=@StuAge,StuSex=@StuSex,StuHobby=@StuHobby,ProfessionID=@ProfessionID where StuID=@StuID"; DBHelper.PrepareSql(sql); DBHelper.SetParameter("StuName", entity.StuName); DBHelper.SetParameter("StuAge", entity.StuAge); DBHelper.SetParameter("StuSex", entity.StuSex); DBHelper.SetParameter("StuHobby", entity.StuHobby); DBHelper.SetParameter("ProfessionID", entity.ProfessionID); DBHelper.SetParameter("StuID", entity.StuID); return DBHelper.ExecNonQuery(); } #endregion #region 列表 public List<StudentInfoEntiy> List() { string sql = "select * from StudentInfo"; DataTable dt = new DataTable(); DBHelper.PrepareSql(sql); dt = DBHelper.ExecQuery(); List<StudentInfoEntiy> list = new List<StudentInfoEntiy>(); foreach (DataRow item in dt.Rows) { StudentInfoEntiy entity = new StudentInfoEntiy(); entity.StuID = item["StuID"].ToString(); entity.StuName = item["StuName"].ToString(); entity.StuAge = int.Parse(item["StuAge"].ToString()); entity.StuSex = item["StuSex"].ToString(); entity.StuHobby = item["StuHobby"].ToString(); entity.ProfessionID = int.Parse(item["ProfessionID"].ToString()); list.Add(entity); } return list; } #endregion #region 详情 public StudentInfoEntiy Detail(string id) { string sql = "select * from StudentInfo where StuID=@StuID"; DataTable dt = new DataTable(); DBHelper.PrepareSql(sql); DBHelper.SetParameter("StuID", id); dt = DBHelper.ExecQuery(); if (dt.Rows.Count == 0) return null; StudentInfoEntiy entity = new StudentInfoEntiy(); entity.StuID = dt.Rows[0]["StuID"].ToString(); entity.StuName = dt.Rows[0]["StuName"].ToString(); entity.StuAge = int.Parse(dt.Rows[0]["StuAge"].ToString()); entity.StuSex = dt.Rows[0]["StuSex"].ToString(); entity.StuHobby = dt.Rows[0]["StuHobby"].ToString(); entity.ProfessionID = int.Parse(dt.Rows[0]["ProfessionID"].ToString()); return entity; } #endregion }
五、业务逻辑层编写
(1)由于业务逻辑层需要使用实体类,所以需要添加实体类的引用。
即在MyBLL项目上右键-->添加-->引用-->项目,在项目中勾选MyEntity项目。
(2)由于业务逻辑层需要调用数据访问层,所以需要添加数据访问层的引用。
即在MyBLL项目上右键-->添加-->引用-->项目,在项目中勾选MyDAL项目。
(3)在MyBLL项目中添加两个类,类代码如下:
ProfessionInfoBLL:
public class ProfessionInfoBLL { ProfessionInfoDAL dal = new ProfessionInfoDAL(); #region 新增 public int Add(ProfessionInfoEntity entity) { return dal.Add(entity); } #endregion #region 删除 public int Delete(int id) { return dal.Delete(id); } #endregion #region 修改 public int Update(ProfessionInfoEntity entity) { return dal.Update(entity); } #endregion #region 列表 public List<ProfessionInfoEntity> List() { return dal.List(); } #endregion #region 详情 public ProfessionInfoEntity Detail(int id) { return dal.Detail(id); } #endregion }
StudentInfoBLL:
public class StudentInfoBLL { StudentInfoDAL dal = new StudentInfoDAL(); #region 新增 public int Add(StudentInfoEntiy entity) { return dal.Add(entity); } #endregion #region 删除 public int Delete(string id) { return dal.Delete(id); } #endregion #region 修改 public int Update(StudentInfoEntiy entity) { return dal.Update(entity); } #endregion #region 列表 public List<StudentInfoEntiy> List() { return dal.List(); } #endregion #region 详情 public StudentInfoEntiy Detail(string id) { return dal.Detail(id); } #endregion }
六、界面UI层代码编写
(1)由于界面UI层需要使用实体类,所以需要添加实体类的引用。
即在MyUI项目上右键-->添加-->引用-->项目,在项目中勾选MyEntity项目。
(2)由于界面UI层需要调用业务逻辑层,所以需要添加业务逻辑层的引用。
即在MyUI项目上右键-->添加-->引用-->项目,在项目中勾选MyBLL项目。
查询窗体界面及代码:
(1)由于查询学生需要多条件组合查询,所以给数据访问层和业务逻辑层添加条件搜索的方法。
给数据访问层MyDAL中StudentInfoDAL类添加方法:
#region 条件查询 public List<StudentInfoEntiy> Search(StudentInfoEntiy searchObj) { string sql = "select * from StudentInfo inner join ProfessionInfo on StudentInfo.ProfessionID = ProfessionInfo.ProfessionID where 1 = 1"; if (searchObj.ProfessionID != 0) sql += " and StudentInfo.ProfessionID = " + searchObj.ProfessionID; if (!searchObj.StuName.Equals("")) sql += " and StuName like '%" + searchObj.StuName + "%'"; DataTable dt = new DataTable(); DBHelper.PrepareSql(sql); dt = DBHelper.ExecQuery(); List<StudentInfoEntiy> list = new List<StudentInfoEntiy>(); foreach (DataRow item in dt.Rows) { StudentInfoEntiy entity = new StudentInfoEntiy(); entity.StuID = item["StuID"].ToString(); entity.StuName = item["StuName"].ToString(); entity.StuAge = int.Parse(item["StuAge"].ToString()); entity.StuSex = item["StuSex"].ToString(); entity.StuHobby = item["StuHobby"].ToString(); entity.ProfessionID = int.Parse(item["ProfessionID"].ToString()); entity.ProfessionName = item["ProfessionName"].ToString(); list.Add(entity); } return list; } #endregion
给业务逻辑层MyBLL中StudentInfoBLL类添加方法:
#region 条件查询 public List<StudentInfoEntiy> Search(StudentInfoEntiy searchObj) { return dal.Search(searchObj); } #endregion
(2)在此界面中多个功能需要调用业务逻辑层,定义两个业务逻辑层对象:
ProfessionInfoBLL proBll = new ProfessionInfoBLL(); StudentInfoBLL stuBll = new StudentInfoBLL();
(3)查询窗体绑定专业信息、绑定学生信息以及搜索功能代码:
#region 绑定下拉框 private void BindPro() { List<ProfessionInfoEntity> list = new List<ProfessionInfoEntity>(); list = proBll.List(); list.Insert(0,new ProfessionInfoEntity { ProfessionID=0,ProfessionName="--请选择--"}); this.cmbPro.DataSource = list; this.cmbPro.DisplayMember = "ProfessionName"; this.cmbPro.ValueMember = "ProfessionID"; } #endregion #region 绑定学生数据 private void BindData() { StudentInfoEntiy searchObj = new StudentInfoEntiy(); searchObj.ProfessionID = int.Parse(this.cmbPro.SelectedValue.ToString()); searchObj.StuName = this.txtName.Text; this.dataGridView1.AutoGenerateColumns = false; this.dataGridView1.DataSource = stuBll.Search(searchObj); } #endregion #region 窗体加载 private void FrmSelect_Load(object sender, EventArgs e) { BindPro(); BindData(); } #endregion #region 搜索按钮 private void btSearch_Click(object sender, EventArgs e) { BindData(); } #endregion
(4)删除菜单代码:
private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) { //添加是否确定删除的对话框 DialogResult result = MessageBox.Show("确定要删除数据吗,删除之后无法恢复!", "提示框", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); if (result == DialogResult.Cancel) return; string stuid = this.dataGridView1.SelectedRows[0].Cells[0].Value.ToString(); if(stuBll.Delete(stuid) == 1) MessageBox.Show("删除成功!"); else MessageBox.Show("删除失败!"); BindData(); }
新增窗体界面及代码:
ProfessionInfoBLL proBll = new ProfessionInfoBLL(); StudentInfoBLL stuBll = new StudentInfoBLL(); #region 绑定下拉框 private void BindPro() { List<ProfessionInfoEntity> list = new List<ProfessionInfoEntity>(); list = proBll.List(); list.Insert(0, new ProfessionInfoEntity { ProfessionID = 0, ProfessionName = "--请选择--" }); this.cmbPro.DataSource = list; this.cmbPro.DisplayMember = "ProfessionName"; this.cmbPro.ValueMember = "ProfessionID"; } #endregion private void FrmAdd_Load(object sender, EventArgs e) { BindPro(); } private void btAdd_Click(object sender, EventArgs e) { //性别处理 string sex = ""; if (this.rbBoy.Checked == true) sex = this.rbBoy.Text; if (this.rbGirl.Checked == true) sex = this.rbGirl.Text; //爱好处理 string hobby = ""; foreach (CheckBox ck in this.panel2.Controls) { if (ck.Checked == true) { if (!hobby.Equals("")) hobby += ","; hobby += ck.Text; } } StudentInfoEntiy entity = new StudentInfoEntiy(); entity.StuID = this.txtId.Text; entity.StuName = this.txtName.Text; entity.StuAge = int.Parse(this.txtAge.Text); entity.StuSex = sex; entity.StuHobby = hobby; entity.ProfessionID = int.Parse(this.cmbPro.SelectedValue.ToString()); if (stuBll.Add(entity) == 1) MessageBox.Show("新增成功!"); else MessageBox.Show("新增失败!"); this.Close(); }
编辑修改窗体界面及代码:
public string StuID { get; set; } //学生编号 ProfessionInfoBLL proBll = new ProfessionInfoBLL(); StudentInfoBLL stuBll = new StudentInfoBLL(); #region 绑定下拉框 private void BindPro() { List<ProfessionInfoEntity> list = new List<ProfessionInfoEntity>(); list = proBll.List(); list.Insert(0, new ProfessionInfoEntity { ProfessionID = 0, ProfessionName = "--请选择--" }); this.cmbPro.DataSource = list; this.cmbPro.DisplayMember = "ProfessionName"; this.cmbPro.ValueMember = "ProfessionID"; } #endregion #region 绑定详情 private void BindDetail() { StudentInfoEntiy entity = new StudentInfoEntiy(); entity = stuBll.Detail(this.StuID); this.txtId.Text = entity.StuID; this.txtName.Text = entity.StuName; this.txtAge.Text = entity.StuAge.ToString(); this.cmbPro.SelectedValue = entity.ProfessionID; //性别处理 if (entity.StuSex.Equals("男")) this.rbBoy.Checked = true; else this.rbGirl.Checked = true; //爱好处理 string[] arrHobby = entity.StuHobby.Split(','); foreach (string hobby in arrHobby) { foreach (CheckBox ck in this.panel2.Controls) { if (ck.Text.Equals(hobby)) ck.Checked = true; } } } #endregion private void FrmEdit_Load(object sender, EventArgs e) { BindPro(); BindDetail(); } private void btUpdate_Click(object sender, EventArgs e) { //性别处理 string sex = ""; if (this.rbBoy.Checked == true) sex = this.rbBoy.Text; if (this.rbGirl.Checked == true) sex = this.rbGirl.Text; //爱好处理 string hobby = ""; foreach (CheckBox ck in this.panel2.Controls) { if (ck.Checked == true) { if (!hobby.Equals("")) hobby += ","; hobby += ck.Text; } } StudentInfoEntiy entity = new StudentInfoEntiy(); entity.StuID = this.txtId.Text; entity.StuName = this.txtName.Text; entity.StuAge = int.Parse(this.txtAge.Text); entity.StuSex = sex; entity.StuHobby = hobby; entity.ProfessionID = int.Parse(this.cmbPro.SelectedValue.ToString()); if (stuBll.Update(entity) == 1) MessageBox.Show("修改成功!"); else MessageBox.Show("修改失败!"); this.Close(); }
查询窗体中"新增"和"编辑"按钮代码:
private void btAdd_Click(object sender, EventArgs e) { FrmAdd frm = new FrmAdd(); frm.Show(); } private void btEdit_Click(object sender, EventArgs e) { string stuid = this.dataGridView1.SelectedRows[0].Cells[0].Value.ToString(); FrmEdit frm = new FrmEdit(); frm.StuID = stuid; frm.Show(); }
到此这篇关于C#使用三层架构开发Winform的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。