winform 三层构架 桌面软件开发 SQLite

2024-02-25 14:32

本文主要是介绍winform 三层构架 桌面软件开发 SQLite,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于三层构架的桌面软件开发

三层架构分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)、实体类库(Model)
分层次的目的:为了“高内聚低耦合”的思想

  • 表示层(UI):主要对用户的请求接受,以及数据的返回,为客户端提供应用程序的访问。
  • 业务逻辑层(BLL):主要负责对数据层的操作。也就是说把一些数据层的操作进行组合。
  • 数据访问层(DAL):主要看数据层里面有没有包含逻辑处理,实际上它的各个函数主要完成各个对数据文件的操作。

各层之间的关系

关系

搭建三层

建立项目,按顺序添加层,每添加一层删除 Programe.cs。

  • 建立其他项目类型-空白解决方法TestFloor
  • 添加TestFloorModel项目类库,右击属性-创建名称空间修改为TestFloor.Model
  • 依次添加TestFloorDAL,TestFloorBLL,UI层即为TestFloor不需要修改
  • 创建联系,TestFloorDAL引用项目TestFloorModel,TestFloorBLL引用项目TestFloorDAL和TestFloorModel,TestFloor引用项目TestFloorModel和TestFloorBLL,其中修改Forms类,直接重命名
  • 在文件夹目录新建DLL文件夹,将外部dll复制过来
  • 在UI中添加应用配置文件App.config用于连接数据库,修改文件内容,将数据库参数内容写入configuration中
<connectionStrings> <add connectionString="Data Source=cater.db;Version=3;" name="conStr"/>
</connectionStrings>
  • 将数据库文件.db放入到项目UI层,BIN-DEBUG文件夹中
  • 在DAL项目添加引用,SQLite.dll,添加类SqliteHelper,在类头添加using System.Data.SQLite;using System.Data
  • 编写SqliteHelper类
    public class SqliteHelper{//连接字符串private static readonly string str = ConfigurationManager.ConnectionStrings["conStr"].ConnectionString;/// <summary>/// 增删该/// </summary>/// <param name="sql">sql语句</param>/// <param name="param">sql参数</param>/// <returns>受影响的行数</returns>public static int ExecuteNonQuery(string sql, params SQLiteParameter[] param){using(SQLiteConnection con= new SQLiteConnection(str))//使用完自动释放资源{using (SQLiteCommand cmd=new SQLiteCommand(sql,con)){con.Open();if (param != null){cmd.Parameters.AddRange(param);}return cmd.ExecuteNonQuery();}}}/// <summary>/// 查询/// </summary>/// <param name="sql">sql语句</param>/// <param name="param">sql参数</param>/// <returns>首行首列</returns>public static object ExecuteScalar(string sql, params SQLiteParameter[] param){using (SQLiteConnection con = new SQLiteConnection(str)){using (SQLiteCommand cmd = new SQLiteCommand(sql, con)){con.Open();if (param != null){cmd.Parameters.AddRange(param);}return cmd.ExecuteScalar();}}}/// <summary>/// 多行查询/// </summary>/// <param name="sql">sql语句</param>/// <param name="param">sql参数</param>/// <returns>SQLiteDataReader</returns>public static SQLiteDataReader ExecuteReader(string sql, params SQLiteParameter[] param){SQLiteConnection con = new SQLiteConnection(str);using (SQLiteCommand cmd = new SQLiteCommand(sql, con)){if (param != null){cmd.Parameters.AddRange(param);}try{con.Open();return cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);}catch (Exception ex){con.Close();con.Dispose();throw ex;}}}/// <summary>/// 查询多行数据/// </summary>/// <param name="sql">sql语句</param>/// <param name="param">sql参数</param>/// <returns>一个表À</returns>public static DataTable ExecuteTable(string sql,params SQLiteParameter[] param){DataTable dt = new DataTable();using (SQLiteDataAdapter sda = new SQLiteDataAdapter(sql,str)){if (param != null){sda.SelectCommand.Parameters.AddRange(param);}sda.Fill(dt);}return dt;}}

至此基本功能完成,下面介绍一个简单的练习数据库的增删改查

增删改查

点击会员管理,实现对会员的增删改查

按钮

点击会员管理,出现会员管理窗体

会员管理窗体

1加载

数据库中会员表,表名为MemberInfo

MemberInfo表

private void btnMember_Click(object sender, EventArgs e)
{FrmMmemberInfo fm =new FrmMmemberInfo();fm.ShowDialog();
}

在窗口加载时需要将现有会员显示出来,若要将所有会员显示出来,传入标识符,返回会员列表

private void FrmMmemberInfo_Load(object sender, EventArgs e)
{//加载会员LoadMemberInfoByDelflag(0);
}

下面要去MODEL中根据表名新建一个model类,MemmberInfo类,该类中成员都为列名

   public class MemmberInfo{//MemberId MemName MemMobilePhone MemAdress MemType MemNum MemGender MemDiscount MemMoney DelFlag SubTime MemIntegral MemEndServerTime MemBirthdaty#region Modelprivate int _memmberid;private string _memname;private string _memphone;private string _memmobilephone;private string _memaddress;private int _memtype;private string _memnum;private string _memgender;private decimal? _memdiscount = 1.00M;private decimal? _memmoney = 0M;private int? _delflag;private DateTime? _subtime;private int? _memintegral;private DateTime? _memendservertime;private DateTime? _membirthdaty;//冗余属性public string MemTpName{get;set;}/// <summary>/// 会员主键id/// </summary>public int MemmberId{set { _memmberid = value; }get { return _memmberid; }}/// <summary>/// 会员名字/// </summary>public string MemName{set { _memname = value; }get { return _memname; }}/// <summary>/// 会员电话/// </summary>public string MemPhone{set { _memphone = value; }get { return _memphone; }}/// <summary>/// 会员手机/// </summary>public string MemMobilePhone{set { _memmobilephone = value; }get { return _memmobilephone; }}/// <summary>/// 会员地址/// </summary>public string MemAddress{set { _memaddress = value; }get { return _memaddress; }}/// <summary>/// 会员类型/// </summary>public int MemType{set { _memtype = value; }get { return _memtype; }}/// <summary>/// 会员编号/// </summary>public string MemNum{set { _memnum = value; }get { return _memnum; }}/// <summary>/// 会员性别/// </summary>public string MemGender{set { _memgender = value; }get { return _memgender; }}/// <summary>/// 会员折扣/// </summary>public decimal? MemDiscount{set { _memdiscount = value; }get { return _memdiscount; }}/// <summary>/// 会员余额/// </summary>public decimal? MemMoney{set { _memmoney = value; }get { return _memmoney; }}/// <summary>/// 会员删除标识/// </summary>public int? DelFlag{set { _delflag = value; }get { return _delflag; }}/// <summary>/// 会员提交时间/// </summary>public DateTime? SubTime{set { _subtime = value; }get { return _subtime; }}/// <summary>/// 会员积分/// </summary>public int? MemIntegral{set { _memintegral = value; }get { return _memintegral; }}/// <summary>/// 会员结束时间/// </summary>public DateTime? MemEndServerTime{set { _memendservertime = value; }get { return _memendservertime; }}/// <summary>/// 会员生日/// </summary>public DateTime? MemBirthdaty{set { _membirthdaty = value; }get { return _membirthdaty; }}#endregion Model}

在DAL层同样的方式新建MemmberInfoDAL类,将private改成public,创建公有方法GetAllMemmberInfoDelflag()同时还涉及到一个行转对象的问题

public List<MemmberInfo> GetAllMemmberInfoDelflag(int delflag)
{string sql="select * from MemmberInfo where DelFlag=@DelFlag";DataTable dt=SqliteHelper.ExecuteTable(sql,new SQLiteParameter("@DelFlag",delflag));List<MemmberInfo> list=new List<MemmberInfo>();if(dt.Rows.Count>0){foreach (DataRow item in dt.Rows){MemmberInfo member=RowToMemberInfo(item); if(list!=null){list.Add(member);}}}return list;
}
/// <summary>
/// 成员转类
/// </summary>
/// <param name="dr"></param>
/// <returns></returns>
private MemmberInfo RowToMemberInfo(DataRow dr)
{MemmberInfo member=new MemmberInfo();member.DelFlag=Convert.ToInt32( dr["DelFlag"]);member.MemAddress=dr["MemAddress"].ToString();member.MemmberId=Convert.ToInt32(dr["MemmberId"]);//member.MemBirthdaty=Convert.ToDateTime(dr["MemBirthdaty"]);member.MemDiscount=Convert.ToDecimal(dr["MemDiscount"]);//member.MemEndServerTime=Convert.ToDateTime(dr["MemEndServerTime"]);member.MemGender=dr["MemGender"].ToString();//member.MemIntegral=Convert.ToInt32(dr["MemIntegral"]);member.MemMobilePhone=dr["MemMobilePhone"].ToString();member.MemMoney=Convert.ToDecimal(dr["MemMoney"]);;member.MemName=dr["MemName"].ToString();member.MemNum=dr["MemNum"].ToString();member.MemType=Convert.ToInt32(dr["MemType"]);member.SubTime=Convert.ToDateTime(dr["SubTime"]);  return member;
}

在BLL层同样的方式新建MemmberInfoBLL类,将private改成public,创建公有方法GetAllMemmberInfoDelflag()

public List<MemmberInfo> GetAllMemmberInfoDelflag(int delflag)
{return dal.GetAllMemmberInfoDelflag(delflag);
}

在UI层中,加载数据

private void LoadMemberInfoByDelflag(int p)
{MemmberInfoBLL bll = new MemmberInfoBLL();dgvmember.AutoGenerateColumns = false;//静止自动生成列dgvmember.DataSource = bll.GetAllMemmberInfoDelflag(p);dgvmember.SelectedRows[0].Selected = false;//默认不选中
}

删除

删除首先要判断是否选中行,然后通过标识进行删除操作,UI层

private void btnDelete_Click(object sender, EventArgs e)
{//判断是否选中某行if (dgvmember.SelectedRows.Count > 0){MemmberInfoBLL bll = new MemmberInfoBLL();int id = Convert.ToInt32(dgvmember.SelectedRows[0].Cells[0].Value);if (bll.DeleteMemberInfoByMemberID(id)){MessageBox.Show("操作成功");LoadMemberInfoByDelflag(0);}else{MessageBox.Show("操作失败");}}else {MessageBox.Show("请先选中要删除的会员");}
}

同样到DAL和BLL层中编写DeleteMemberInfoByMemberID()方法
在DAL的MemmberInfoDAL类中

/// <summary>
/// 根据id删除会员
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public int DeleteMemberInfoByMemberID(int id)
{//用户传的需要写参数,不是可以不用写参数string sql = "update MemmberInfo set DelFlag=1 where MemmberId=@MemmberId";return   SqliteHelper.ExecuteNonQuery(sql,new SQLiteParameter("@MemmberId",id));
}

在BLL的MemmberInfoBLL类中

/// <summary>
/// 根据ID删值
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool DeleteMemberInfoByMemberID(int id)
{return dal.DeleteMemberInfoByMemberID(id)>0 ? true:false;
}

增加和修改

增加和修改窗体

这两个功能可以放到一起做,通过事件向窗体传值FrmChanfeMember窗体

//为了传值在UI层新建消息类
//窗体传值用的类
public class FrmEventArgs : EventArgs
{/// <summary>/// 标识/// </summary>public int Temp { set; get; }/// <summary>/// 对象/// </summary>public Object obj { set; get; }
}
/// <summary>
/// 窗体传值事件
/// </summary>
public event EventHandler evt;
/// <summary>
/// 事件参数类
/// </summary>
FrmEventArgs fea = new FrmEventArgs();
//点击增加
private void btnAddMember_Click(object sender, EventArgs e)
{
//ShowFrmChangeMember(2);
fea.Temp = 2;
ShowFrmChangeMember();
}
//点击修改
private void btnUpdeMember_Click(object sender, EventArgs e)
{if (dgvmember.SelectedRows.Count > 0){int id = Convert.ToInt32(dgvmember.SelectedRows[0].Cells[0].Value);//不能从表中直接拿值,要从数据库中查询MemmberInfoBLL bll = new MemmberInfoBLL();fea.Temp = 1;fea.obj = bll.GetMemberInfoByID(id);//从数据库中根据ID取值ShowFrmChangeMember();}else{MessageBox.Show("请选中要修改的会员");}//ShowFrmChangeMember(1);}
private void ShowFrmChangeMember()
{FrmChanfeMember fcm = new FrmChanfeMember();this.evt += new EventHandler(fcm.SetText);//fea.Temp = p;//新增或修改的表示if (this.evt != null)//执行事件之前不能为空{this.evt(this, fea);//执行事件}//fcm.ShowDialog();他关闭将子窗口中值传递给父类窗口fcm.FormClosed += new FormClosedEventHandler(fcmFrmClosed);fcm.ShowDialog();
}
//窗口关闭更新界面
private  void fcmFrmClosed(object sender,EventArgs e)
{LoadMemberInfoByDelflag(0);}

在FrmChanfeMember中传值函数

public void SetText(object sender,EventArgs e)
{loadMemmberType();FrmEventArgs fea = e as FrmEventArgs;temp = fea.Temp;//if (fea.Temp == 2)//新增修改//{foreach (var item in this.Controls){if (item is TextBox){TextBox tb = item as TextBox;tb.Text = "";}}//}if(fea.Temp==1){MemmberInfo member=fea.obj as MemmberInfo;if (member != null){txtMemNum.Text = member.MemNum.ToString();txtAddress.Text = member.MemAddress.ToString();txtMemDiscount.Text = member.MemDiscount.ToString();txtMemIntegral.Text = member.MemIntegral.ToString();txtmemMoney.Text = member.MemMoney.ToString();txtMemName.Text = member.MemName.ToString();txtMemPhone.Text = member.MemMobilePhone.ToString();txtBirs.Text = member.MemBirthdaty.ToString();cmbMemType.SelectedIndex = Convert.ToInt32(member.MemType);rdoMan.Checked = member.MemGender=="男"?true:false;rdoWomen.Checked=member.MemGender=="女"?true:false;labId.Text = member.MemmberId.ToString();//将ID存起来}}else{txtMemIntegral.Text = "0";}}
public void loadMemmberType()
{MemmberTypeBLL bll = new MemmberTypeBLL();List<MemmberType> list = bll.GetMemmberType();list.Insert(0, new MemmberType() { MemType = -1, MemTpName = "请选择" });cmbMemType.DataSource = list;cmbMemType.DisplayMember = "MemTpName";cmbMemType.ValueMember = "MemType";
}
/// <summary>
/// 判断是新增还是修改
/// </summary>
private int temp{set;get;}
private void btnOk_Click(object sender, EventArgs e)
{//获取会员信息//每个文本框不能为空//判断性别MemmberInfo mem=new MemmberInfo();if(CheckMemmberTextEmpty()){mem.MemAddress = txtAddress.Text;mem.MemBirthdaty = Convert.ToDateTime(txtBirs.Text);mem.MemDiscount = Convert.ToDecimal(txtMemDiscount.Text);mem.MemEndServerTime = dtEndServerTime.Value;mem.MemGender = CheckGender();mem.MemIntegral = Convert.ToInt32(txtMemIntegral.Text);mem.MemMobilePhone = txtMemPhone.Text;mem.MemMoney = Convert.ToDecimal(txtmemMoney.Text);mem.MemName = txtMemName.Text;mem.MemNum = txtMemNum.Text;mem.MemType = Convert.ToInt32(cmbMemType.SelectedIndex);}MemmberInfoBLL bll = new MemmberInfoBLL();if (temp == 2){mem.DelFlag = 0;mem.SubTime = System.DateTime.Now; }if (temp == 1){mem.MemmberId = Convert.ToInt32(labId.Text);}string str = bll.SaveMember(mem, this.temp) ? "操作成功" : "操作失败";MessageBox.Show(str);this.Close();
}
public bool CheckMemmberTextEmpty()
{if (string.IsNullOrEmpty(txtBirs.Text)){MessageBox.Show("生日不能为空");return false;}if (string.IsNullOrEmpty(txtMemDiscount.Text)){MessageBox.Show("折扣不能为空");return false;}if (string.IsNullOrEmpty(txtMemIntegral.Text)){MessageBox.Show("积分不能为空");return false;}if (string.IsNullOrEmpty(txtmemMoney.Text)){MessageBox.Show("余额不能为空");return false;}if (string.IsNullOrEmpty(txtMemName.Text)){MessageBox.Show("名字不能为空");return false;}if (string.IsNullOrEmpty(txtMemNum.Text)){MessageBox.Show("编号不能为空");return false;}if (string.IsNullOrEmpty(txtMemPhone.Text)){MessageBox.Show("电话不能为空");return false;}if (string.IsNullOrEmpty(dtEndServerTime.Text)){MessageBox.Show("有效期不能为空");return false;}return true;
}
public string CheckGender()
{string str="";if (rdoMan.Checked){str = "男";}if(rdoWomen.Checked){str = "女";}return str;
}

点击OK将数据保存数据库,BLL层在该层中要进行逻辑判断是新增还是修改

public bool SaveMember(MemmberInfo memmber, int temp)
{int flag = -1;if (temp == 2){flag= dal.AddMemmberInfo(memmber);}if (temp == 1){flag= dal.UpdataAddMemberInfo(memmber);}return flag>0?true:false;
}
/// <summary>
/// 根据id查值
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public MemmberInfo GetMemberInfoByID(int id)
{return dal.GetMemberInfoByID(id);
}

DAL层


public int AddMemmberInfo(MemmberInfo memmber)
{string sql = "insert into MemmberInfo(MemName,MemMobilePhone,MemAddress,MemType,MemNum,MemGender,MemDiscount,MemMoney,DelFlag,SubTime,MemIntegral,MemEndServerTime,MemBirthdaty)values(@MemName,@MemMobilePhone,@MemAddress,@MemType,@MemNum,@MemGender,@MemDiscount,@MemMoney,@DelFlag,@SubTime,@MemIntegral,@MemEndServerTime,@MemBirthdaty)";return AddAndUpdate(memmber, sql, 1);
}
public int UpdataAddMemberInfo(MemmberInfo memmber)
{string sql = "update MemmberInfo set MemName=@MemName,MemMobilePhone=@MemMobilePhone,MemAddress=@MemAddress,MemType=@MemType,MemNum=@MemNum,MemGender=@MemGender,MemDiscount=@MemDiscount,MemMoney=@MemMoney,MemIntegral=@MemIntegral,MemEndServerTime=@MemEndServerTime,MemBirthdaty=@MemBirthdaty where MemmberId=@MemmberId";return AddAndUpdate(memmber, sql, 2);
}
//新增和修改的合并方法
private int AddAndUpdate(MemmberInfo memmber, string sql, int temp)
{SQLiteParameter[] param = { new SQLiteParameter("@MemName",memmber.MemName),new SQLiteParameter("@MemMobilePhone",memmber.MemMobilePhone),new SQLiteParameter("@MemAddress",memmber.MemAddress),new SQLiteParameter("@MemType",memmber.MemType),new SQLiteParameter("@MemNum",memmber.MemNum),new SQLiteParameter("@MemGender",memmber.MemGender),new SQLiteParameter("@MemDiscount",memmber.MemDiscount),new SQLiteParameter("@MemMoney",memmber.MemMoney),// new SQLiteParameter("@MemmberId",memmber.MemmberId),new SQLiteParameter("@MemIntegral",memmber.MemIntegral),new SQLiteParameter("@MemEndServerTime",memmber.MemEndServerTime),new SQLiteParameter("@MemBirthdaty",memmber.MemBirthdaty)};List<SQLiteParameter> list = new List<SQLiteParameter>();list.AddRange(param);if (temp == 1)//新增{list.Add(new SQLiteParameter("@SubTime", memmber.SubTime));list.Add(new SQLiteParameter("@DelFlag", memmber.DelFlag));}else if (temp == 2)//修改{list.Add(new SQLiteParameter("@MemmberId", memmber.MemmberId));}return SqliteHelper.ExecuteNonQuery(sql, list.ToArray());
}
public MemmberInfo GetMemberInfoByID(int id)
{MemmberInfo member = null;string sql = "select * from MemmberInfo where MemmberId=@MemmberId";DataTable dt = SqliteHelper.ExecuteTable(sql, new SQLiteParameter("@MemmberId", id));if (dt.Rows.Count > 0){member = RowToMemberInfo(dt.Rows[0]);}return member;
}

自此三层框架中的增删改查介绍完毕。

这篇关于winform 三层构架 桌面软件开发 SQLite的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/745768

相关文章

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

C# winform操作CSV格式文件

《C#winform操作CSV格式文件》这篇文章主要为大家详细介绍了C#在winform中的表格操作CSV格式文件的相关实例,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下... 目录实例一实例效果实现代码效果展示实例二实例效果完整代码实例一实例效果当在winform界面中点击读取按钮时 将csv中

基于WinForm+Halcon实现图像缩放与交互功能

《基于WinForm+Halcon实现图像缩放与交互功能》本文主要讲述在WinForm中结合Halcon实现图像缩放、平移及实时显示灰度值等交互功能,包括初始化窗口的不同方式,以及通过特定事件添加相应... 目录前言初始化窗口添加图像缩放功能添加图像平移功能添加实时显示灰度值功能示例代码总结最后前言本文将

C#实现WinForm控件焦点的获取与失去

《C#实现WinForm控件焦点的获取与失去》在一个数据输入表单中,当用户从一个文本框切换到另一个文本框时,需要准确地判断焦点的转移,以便进行数据验证、提示信息显示等操作,本文将探讨Winform控件... 目录前言获取焦点改变TabIndex属性值调用Focus方法失去焦点总结最后前言在一个数据输入表单

C#实现文件读写到SQLite数据库

《C#实现文件读写到SQLite数据库》这篇文章主要为大家详细介绍了使用C#将文件读写到SQLite数据库的几种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下... 目录1. 使用 BLOB 存储文件2. 存储文件路径3. 分块存储文件《文件读写到SQLite数据库China编程的方法》博客中,介绍了文

sqlite不支持中文排序,采用java排序

方式一 不支持含有重复字段进行排序 /*** sqlite不支持中文排序,改用java排序* 根据指定的对象属性字段,排序对象集合,顺序* @param list* @param field* @return*/public static List sortListByField(List<?> list,String field){List temp = new ArrayList(

Python知识点:如何使用Python开发桌面应用(Tkinter、PyQt)

Python 提供了多个库来开发桌面应用程序,其中最常见的两个是 Tkinter 和 PyQt。这两者各有优点,选择取决于你的需求。以下我会介绍如何使用 Tkinter 和 PyQt 开发简单的桌面应用程序。 1. 使用 Tkinter 开发桌面应用 Tkinter 是 Python 的标准库,它非常轻量级且跨平台。它适合开发简单的桌面应用,入门较容易。 安装 Tkinter Tkinte

【软件工程】软件开发模型

三、瀑布模型  四、几种软件开发模型的主要特点 题目 判断题 选择题 小结

一不小心给桌面粘贴了1280个文件怎么办?

搞了一下午很混乱,慌乱中不小心将一个文件夹里的1280个包粘贴在了桌面上,         完后都没有撤销粘贴这个鼠标右键功能,反而还可以再粘贴。         很懵逼,只能把桌面上可以看见的多余文件删除,那么看不见的呢又拽不出来。         同时发现刷新桌面会很有明显的卡顿,说明那些文件确实还存在着,比之前的响应速度慢多了。         苦逼中去百度了一下然而