C# Winform 三层架构

news/2025/2/20 9:20:52/

一、介绍

三层架构是 C# 桌面开发中比较常用的框架,是由 表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构组成,目的是为了 “高内聚,低耦合”。开发人员分工更明确,将精力更专注于应用系统核心业务逻辑的分析、设计和开发,加快项目的进度,提高了开发效率,有利于项目的更新和维护工作。

从三层架构可以看到,很类似于 Web 前端开发的 MVC 框架(视图View,模型Model,控制Contorller),但本质上也有不同的地方,比如都有视图(三层中叫 UI),Model ,三层中没有 Contorller,但 BLL 层和 Contorller 很类似。

一个项目如果用到了三层架构,这就必然要涉及到数据库,否则就没有必要用三层架构了,下面用一张图来表示,我百度看了很多的帖子,三层架构写的基本是有一些差异的,如果你看的资料和我写的不一样,那都是正常的。

另外,各种项目根据自己的需求来,并不是所有的PC软件都要求用三层架构,用程序集划分了代码的逻辑,才是三层架构真正的意义所在。现在网上已经有很多三层架构自动生成生成软件,可以根据 sqlserver 数据库一键生成,但基本都是2016年之前的软件了,后面也没再更新了,有需要的话可以去试试。

二、搭建三层架构

新建一个基于.net6 的 winform 项目,就以登陆功能作为演示,界面如下

1.Model

添加一个 .net6 类库,取名 Model(存储数据库字段),在里面添加一个类 UserInfo

代码:

namespace Model
{public class UserInfo{public string? UserName { get; set; }public string? Password { get; set; }}
}

一般你数据库用户表的所有字段都要写出来,主要是方便后面将查询的数据以类对象的方式返回回来。

2.DAL

添加一个 .net6 类库,取名 DAL(数据访问层),在里面添加一个类 SqlServerHelper,这里看你用的什么数据库,如果是 mysql 就用 mysql 的查询方式,c# 查询 mysql 和 sqlserver 数据库我都有写相关的教程,有需要的可以去看看

C# 连接 SqlServer 数据库_熊思宇的博客-CSDN博客_c连接sqlserver数据库

C# 连接 MySQL 数据库_熊思宇的博客-CSDN博客_c# mysql

SqlServerHelper.cs

using System.Data;
using System.Data.SqlClient;namespace SqlServer
{internal class SqlServerHelper{/// <summary>/// 连接字符串/// </summary>private string strconn = string.Empty;public SqlServerHelper(string conn){//读取配置文件//strconn = ConfigurationManager.AppSettings["Conn"].ToString();//strconn = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();strconn = conn;}/// <summary>/// 执行增删改SQL语句/// </summary>/// <param name="cmdText">SQL语句</param>/// <returns></returns>public int ExecuteNonQuery(string cmdText){using (SqlConnection conn = new SqlConnection(strconn)){conn.Open();return ExecuteNonQuery(conn, cmdText);}}/// <summary>/// 执行增删改SQL语句/// </summary>/// <param name="conn">SqlConnection</param>/// <param name="cmdText">SQL语句<</param>/// <returns></returns>public int ExecuteNonQuery(SqlConnection conn, string cmdText){int res;using (SqlCommand cmd = new SqlCommand(cmdText, conn)){cmd.CommandType = CommandType.Text;res = cmd.ExecuteNonQuery();if (conn.State == ConnectionState.Open){conn.Close();conn.Dispose();}}return res;}/// <summary>/// 执行查询SQL语句/// </summary>/// <param name="cmdText">SQL语句</param>/// <returns></returns>public DataTable ExecuteDataTable(string cmdText){using (SqlConnection conn = new SqlConnection(strconn)){conn.Open();return ExecuteDataTable(conn, cmdText);}}/// <summary>/// 执行查询SQL语句/// </summary>/// <param name="conn">SqlConnection</param>/// <param name="cmdText">SQL语句</param>/// <returns></returns>private DataTable ExecuteDataTable(SqlConnection conn, string cmdText){DataTable dt = new DataTable();using (SqlCommand cmd = new SqlCommand(cmdText, conn)){cmd.CommandType = CommandType.Text;using (SqlDataAdapter sda = new SqlDataAdapter(cmd)){sda.Fill(dt);if (conn.State == ConnectionState.Open){conn.Close();conn.Dispose();}}}return dt;}/// <summary>/// 执行查询SQL语句/// </summary>/// <param name="cmdText">SQL语句</param>/// <returns></returns>public DataTable ExecuteQuery(string cmdText){using (SqlConnection conn = new SqlConnection(strconn)){conn.Open();return ExecuteQuery(conn, cmdText);}}/// <summary>/// 执行查询SQL语句/// </summary>/// <param name="conn">SqlConnection</param>/// <param name="cmdText">SQL语句</param>/// <returns></returns>public DataTable ExecuteQuery(SqlConnection conn, string cmdText){DataTable dt = new DataTable();using (SqlCommand cmd = new SqlCommand(cmdText, conn)){using (SqlDataReader sdr = cmd.ExecuteReader()){dt.Load(sdr);sdr.Close();sdr.Dispose();if (conn.State == ConnectionState.Open){conn.Close();conn.Dispose();}}}return dt;}}
}

如果确少对应的插件,可以自己装一个

新建一个类 UserHandle,用来查询数据库并返回数据

using System.Data;namespace DAL
{public class UserHandle{private const string Conn = "server=.;dataBase=Test;uid=sa;pwd=123456";private static SqlServerHelper SqlServerHelpers = new SqlServerHelper(Conn);/// <summary>/// 用户登录/// </summary>/// <param name="name"></param>/// <param name="pwd"></param>/// <returns></returns>public static DataTable UserLogin(string name ,string pwd){// SQL 语句根据个人情况来写string sql = "SELECT * FROM **********";return SqlServerHelpers.ExecuteDataTable(sql);}/// <summary>/// 获取用户的所有数据/// </summary>/// <param name="name"></param>/// <returns></returns>public static DataTable GetUserData(string name){// SQL 语句根据个人情况来写string sql = "SELECT * FROM *************";return SqlServerHelpers.ExecuteDataTable(sql);}}
}

3.BLL

添加一个 .net6 类库,取名 BLL(业务逻辑层),由于后面的代码需要获取到数据库数据,所以要添加 DAL 和 Model 程序集 的引用

 添加一个类 LoginHandle

using DAL;
using Model;
using System.Data;namespace BLL
{public class LoginHandle{/// <summary>/// 用户登录/// </summary>/// <param name="username">用户名</param>/// <param name="password">密码</param>/// <returns>是否能够登录</returns>public static bool UserLogin(string username, string password){DataTable dataTable = UserHandle.UserLogin(username, password);if (dataTable == null || dataTable.Rows.Count == 0){Console.WriteLine("查询的数据为空");return false;}string? user = dataTable.Rows[0][0].ToString();string? pwd = dataTable.Rows[0][1].ToString();if (username.Equals(user) && password.Equals(pwd)){return true;}return false;}/// <summary>/// 获取用户的所有数据/// </summary>/// <param name="username"></param>/// <returns></returns>public static UserInfo? GetUserData(string username){DataTable dataTable = UserHandle.GetUserData(username);if (dataTable == null || dataTable.Rows.Count == 0){Console.WriteLine("查询的数据为空");return null;}UserInfo userInfo = new UserInfo();userInfo .UserName = dataTable.Rows[0][0].ToString();userInfo .Password = dataTable.Rows[0][1].ToString();return userInfo;}}
}

4.UI

UI层就是创建项目时的 winform 项目,上面的工作完成后,配置大概就如下界面

接下来就添加项目引用了,将 BLL和 Model 层添加进来

给界面的登录按钮,添加点击事件

using BLL;
using Model;namespace 三层架构Demo
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void Button_Login_Click(object sender, EventArgs e){string username = TextBox_UserName.Text;string password = TextBox_Password.Text;if(string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)){Console.WriteLine("输入框不能为空");return;}//第一种方式bool result = LoginHandle.UserLogin(username, password);if(result){Console.WriteLine("登录成功!");//跳转界面//....}else{Console.WriteLine("登录失败");}//第二种方式UserInfo? userInfo = LoginHandle.GetUserData(username);if(userInfo != null){if(userInfo.Password != password){Console.WriteLine("密码不正确");return;}Console.WriteLine("登录成功!");}}}
}

 源码:点击下载

结束

如果这个帖子对你有所帮助,欢迎 关注 、点赞 、留言

end


http://www.ppmy.cn/news/6218.html

相关文章

【并发】深入理解JMM并发三大特性(一)

【并发】深入理解JMM&并发三大特性&#xff08;一&#xff09; 今天是2022.11.16&#xff0c;在此之前我已经学习完了图灵课堂MySQL的课程&#xff0c;也是想这篇文章一样用CSDN博客的形式来记录这些知识点。 在并发中&#xff0c;JMM在大多数人眼中&#xff0c;它是整个…

java中的反射

反射 类加载的过程 当程序主动使用某个类时&#xff0c;如果该类还未被加载到内存中&#xff0c;则JVM会通过加载、连接、初始化3个步骤来对该类进行初始化。如果没有意外&#xff0c;JVM将会连续完成3个步骤&#xff0c;所以有时也把这个3个步骤统称为类加载或类初始化。加载 …

从 2022 年优秀 Linux 发行版中挑选你喜欢的版本

导读如果你想从 2022 年最佳 Linux 发行版列表中挑选一个最喜欢的版本&#xff0c;那么今天你需要考虑以下几个选项。 2022 年是充满惊喜的一年&#xff0c;Linux 发行版的表现也不例外。从充满功能的新版本到各种桌面选项&#xff0c;总有一些值得期待的东西。 如果你想从 20…

Promise对象的使用

一、什么是Promise Promise 是异步编程的一种解决方案&#xff0c;比传统的解决方案&#xff08;回调函数和事件&#xff09;更合理和更强大。从语法上说&#xff0c;Promise 是一个对象&#xff0c;从它可以获取异步操作的消息。Promise 提供统一的 API&#xff0c;各种异步操…

让人恶心的多线程代码,性能怎么优化?

Java 中最烦人的&#xff0c;就是多线程&#xff0c;一不小心&#xff0c;代码写的比单线程还慢&#xff0c;这就让人非常尴尬。 通常情况下&#xff0c;我们会使用 ThreadLocal 实现线程封闭&#xff0c;比如避免 SimpleDateFormat 在并发环境下所引起的一些不一致情况。其实…

小程序02/小程序 页面生命周期钩子函数、组件生命周期钩子函数

一. 页面生命周期钩子函数 onLoad 监听页面加载 onShow 监听页面显示 onReady 监听页面初次渲染完成 onHide 监听页面隐藏 onUnload 监听页面清除消失 onPullDownRefresh 监听用户…

Redis Lua拓展及使用示例

本文主要介绍 Lua 脚本的安全性问题、以及解决这些问题的方法进行说明&#xff0c; 及对执行 Lua 脚本EVAL的实现原理进行介绍&#xff0c;最后还有Lua的相关示例。 Lua 脚本功能是 Reids 2.6 版本的最大亮点&#xff0c; 通过内嵌对 Lua 环境的支持&#xff0c; Redis 解决了…

Java 8 Stream 从入门到进阶——像SQL一样玩转集合

0.阅读完本文你将会 了解Stream的定义和它的特征了解Stream的基础和高阶用法 1. 前言 在我们日常使用Java的过程中&#xff0c;免不了要和集合打交道。对于集合的各种操作有点类似于SQL——增删改查以及聚合操作&#xff0c;但是其方便性却不如SQL。 所以有没有这样一种方式…