基于C#.NET的WinForm项目,我们经常使用基于三层架构,来构建项目框架,这里简单的梳理一下三层架构的相关知识

哪三层?


我们通常所说的三层框架指的是DAL、BIL和UIL三层,分别是数据层、业务逻辑层和界面层,以及与之搭配的实体类和通用类库,下面分别概述

实体类- Model

  • 我们将数据存放在数据库中,数据表的结构,我们通常会用一个类来抽象,表的属性就是类的属性,我们通常将表的一行存储在一个类中。我们在Java中,通常将其称为实体类Entity,在C#中,我们通常将其称为Model。
  • 如图,我们定义了一个数据表,表结构如下

    表结构

  • 我们根据表的信息,创建了如下的实体类
namespace mtWeightModel
{[Serializable] //表示可以序列化public class User{public int Id { get; set; }public String username { get; set; }public String password { get; set; }public int status { get; set; }}
}
  • 我们可以看到,在SQLServer数据库中,char varchar nchar nvarchar都用String类型,int就对应Int。
  • Model类库一般来说需要被DAL、BIL和UI引用。

DAL-数据访问层 - DataAccessLayer

  • 数据访问层,就是调用我们数据库访问方法,专注于数据的增删改查操作,构建SQL语句,构建参数等,以下是一个典型DAL方法
namespace mtWeightDAL
{/// <summary>/// 用户访问数据类/// </summary>public class UserService{/// <summary>/// 根据账号和密码比对用户信息/// </summary>/// <param name="objUser">包含用户名和密码的用户对象</param>/// <returns>返回用户对象信息(若无用户信息则对象为null)</returns>public User UserLogin(User objUser) {String sql = "SELECT Id,username,password,status FROM Users where username=@username and password=@password";SqlParameter[] param = new SqlParameter[] {new SqlParameter("@username",objUser.username),new SqlParameter("@password", objUser.password)};SqlDataReader objReader = SqlHelper.getReader(sql, param);if (objReader.Read()){objUser.Id = Convert.ToInt32(objReader["Id"]);objUser.status = Convert.ToInt32(objReader["status"]);}else {objUser = null;}objReader.Close();return objUser;}}
}
  • 这里用到了一个SqlHelper类,使我们后面要单独说的数据库帮助类
  • DAL就是根据业务需求,构建SQL语句,构建参数,调用帮助类,获取结果,DAL层被BIL层调用

BLL-业务逻辑层 - Business Logic Layer

  • BLL层索要负责的,就是处理业务逻辑上的问题,比如在调用数据库访问之前,对数据的处理、判断等。下面是一个最简单的业务逻辑方法,不处理任何信息,只做参数传递。
namespace mtWeightBLL
{/// <summary>/// 用户业务逻辑类/// </summary>public class UserManager{//创建数据访问对象private UserService objUserService = new UserService();public User UserLogin(User objUser) {return objUserService.UserLogin(objUser);}}
}
  • 那你可能就会有疑问,为什么不把业务逻辑和数据访问合在一起呢,偏要搞出两个层,不是多此一举么。那其实呢,我们分层解决问题的意义就是,功能专一,并且解耦我们的程序,我们在DAL层只关心我的数据库访问操作,我默认你给我的数据是合法的、正确的,那至于你如何保证数据的合法性和正确性就是你需要在BLL层里去做的了。
  • BLL层只被UIL层引用

UIL-用户表现层

  • 就是窗体Form
  • 这里有一个click事件
private void btnLogin_Click(object sender, EventArgs e){//数据验证if (this.txtUsername.Text.Trim().Length == 0) {MessageBox.Show("请输入用户名", "登录提示");this.txtUsername.Focus();}if (this.txtPassword.Text.Trim().Length == 0){MessageBox.Show("请输入密码", "登录提示");this.txtPassword.Focus();}// 封装对象User objUser = new User {username = this.txtUsername.Text.Trim(),password = this.txtPassword.Text.Trim()};try{objUser = objUserManager.UserLogin(objUser);if (objUser != null){if (objUser.status == 1){Program.objCurrentUser = objUser;this.DialogResult = DialogResult.OK;this.Close();}else{MessageBox.Show("用户被禁用,请联系管理员", "登录提示");}}else {MessageBox.Show("用户名或密码错误!", "登录提示");}}catch (Exception ex){MessageBox.Show("登录异常:"+ex.Message,"登录提示");}}

通用类库

  • 对于一些程序中用到的其他封装的类库,可以统一放在这里,比如一些第三方类库等

引用关系


引用关系图

数据库帮助类


  • 我们可以用过封装ADO.NET形成自己的一套方法,但是我们知道在ADO.NET中,SQLServer、Access、Mysql和Oracle使用的是不同的类,那么我们可能需要对每一个数据库封装一套帮助类。其中常用的方法包括非查询类方法(两个重载[sql],[sql,参数])和查询类方法(两个重载[sql],[sql,参数]),事务类方法、存储过程类方法等。
  • 我们通常为会先规定一个接口,然后在帮助类中实现结构。这样后期可以通过反射或工厂的方式来实现不同数据库的切换(后面另说)。
  • 下面是我定义的一个简单的数据库帮助类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;namespace DbUtil
{public class SqlHelper{private static String ConnString = ConfigurationManager.ConnectionStrings["ConnString"].ToString();#region 格式化SQL语句/// <summary>/// 增删改非查询类方法/// </summary>/// <param name="sql">SQL语句</param>/// <returns></returns>public static int UPDATE(string sql) {SqlConnection conn = new SqlConnection(ConnString);SqlCommand cmd = new SqlCommand(sql, conn);try{conn.Open();return cmd.ExecuteNonQuery();}catch (Exception ex){throw new Exception(ex.Message);}finally {conn.Close();}}/// <summary>/// 返回单条结果查询类方法/// </summary>/// <param name="sql">SQL语句</param>/// <returns></returns>public static object getSingleResult(string sql){SqlConnection conn = new SqlConnection(ConnString);SqlCommand cmd = new SqlCommand(sql, conn);try{conn.Open();return cmd.ExecuteScalar();}catch (Exception ex){throw new Exception(ex.Message);}finally{conn.Close();}}/// <summary>/// 多条结果查询类方法/// </summary>/// <param name="sql">SQL语句</param>/// <returns></returns>public static SqlDataReader getReader(string sql){SqlConnection conn = new SqlConnection(ConnString);SqlCommand cmd = new SqlCommand(sql, conn);try{conn.Open();return cmd.ExecuteReader(CommandBehavior.CloseConnection);}catch (Exception ex){conn.Close();throw new Exception(ex.Message);}}/// <summary>/// 返回DataSet数据集方法/// </summary>/// <param name="sql">SQL语句</param>/// <returns>结果集DataSet</returns>public static DataSet getDataSet(string sql){SqlConnection conn = new SqlConnection(ConnString);SqlCommand cmd = new SqlCommand(sql, conn);SqlDataAdapter adapter = new SqlDataAdapter(cmd);DataSet ds = new DataSet();try{conn.Open();adapter.Fill(ds);return ds;}catch (Exception ex){throw new Exception(ex.Message);}finally {conn.Close();}}#endregion#region 带参数SQL语句/// <summary>/// 增删改非查询类方法/// </summary>/// <param name="sql">SQL语句</param>/// <param name="param">SQl参数</param>/// <returns></returns>public static int UPDATE(string sql,SqlParameter[] param){SqlConnection conn = new SqlConnection(ConnString);SqlCommand cmd = new SqlCommand(sql, conn);try{conn.Open();cmd.Parameters.AddRange(param);return cmd.ExecuteNonQuery();}catch (Exception ex){throw new Exception(ex.Message);}finally{conn.Close();}}/// <summary>/// 返回单条结果查询类方法/// </summary>/// <param name="sql">SQL语句</param>/// <param name="param">SQL参数</param>/// <returns></returns>public static object getSingleResult(string sql, SqlParameter[] param){SqlConnection conn = new SqlConnection(ConnString);SqlCommand cmd = new SqlCommand(sql, conn);try{conn.Open();cmd.Parameters.AddRange(param);return cmd.ExecuteScalar();}catch (Exception ex){throw new Exception(ex.Message);}finally{conn.Close();}}/// <summary>/// 多条结果查询类方法/// </summary>/// <param name="sql">SQL语句</param>/// <param name="param">SQL参数</param>/// <returns></returns>public static SqlDataReader getReader(string sql,SqlParameter[] param){SqlConnection conn = new SqlConnection(ConnString);SqlCommand cmd = new SqlCommand(sql, conn);try{conn.Open();cmd.Parameters.AddRange(param);return cmd.ExecuteReader(CommandBehavior.CloseConnection);}catch (Exception ex){conn.Close();throw new Exception(ex.Message);}}#endregion}
}

项目创建

  • 首先创建解决方案的过程中,创建默认项目Windows窗体应用程序UIL
  • 然后分别在解决方案中添加类库项目DAL、BLL和CL(通用类库)和Model
  • 然后新建一个DBUtil类库,里面放SQLHeader类
  • 下面添加引用,从下网往上添加,先给DAL添加Model和DBHelper的引用,再为BLL添加DAL和Model的引用,再为UIL添加BLL和Model引用,然后在为需要使用通用类库的项目添加CL的引用。
  • 引用完成后:

C# WinForm项目三层架构简述相关推荐

  1. 在winform中使用三层架构学习总结

    Winform 三层架构小例子 http://www.cnblogs.com/jacky73/archive/2009/09/01/1558083.html 在web开发中常常用到工厂模式三层架构,现 ...

  2. [.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言...

    前言: 关于不同框架实现同一个TaskVision: 前面DebugLZQ先是用WPF(没有使用MVVM,因为前面使用MVVM实现过过点餐系统),因而这个关键点就放在了WPF的Binding上面: 然 ...

  3. b2c项目基础架构分析(一)b2c 大型站点方案简述 已补充名词解释

    b2c项目基础架构分析(一)b2c 大型站点方案简述 已补充名词解释 我最近一直在找适合将来用于公司大型bs,b2b b2c的基础架构. 实际情况是要建立一个bs架构b2b.b2c的网站,当然还包括w ...

  4. Winform 三层架构小例子

    在web开发中常常用到工厂模式三层架构,现在也在Winform中应用这种架构方式,尝试了很多,也模仿了经典例子PetShop,但是还是不行,也参考了网上的一些例子.现在把我这个例子的整个制作过程简单的 ...

  5. CS通用项目系统搭建——三层架构第一天

    CS通用项目:使用三层架构进行搭建 三层架构: 表现层(UI(User Interface)):展示给用户的层面,包含窗体控件数据等信息. 业务逻辑层(BLL(Business Logic Layer ...

  6. 快速实现dNet三层架构项目图解

    开发工具使用SharpDevelop,示例数据库使用微软提供的Northwind.mdb英文版:搭建dNet三层架构项目: 新建UI层:这层可以是web,也可以是form:这里使用form: 新建三个 ...

  7. Java-GUI编程实战之管理系统 Day1【项目开发流程、软件三层架构、项目需求、项目结构分析】

    视频.课件.源码[链接:https://pan.baidu.com/s/13ffqGDzH-DZib6-MFViW3Q 提取码:zjxs] Java-GUI编程实战之管理系统 Day1[项目开发流程. ...

  8. java三层架构是不是策略模式,把「策略模式」应用到实际项目中

    无论你知不知道这个设计模式,但必定在项目中都似曾相识.倘若仅仅聊理论必然枯燥乏味,只有理论和实战相结合方可达到人剑合一的境界. 首先,我来说个需求,倘若是你遇到该如何做?你可停留几分钟,想出你的解决方 ...

  9. MVC项目实践,在三层架构下实现SportsStore-03,Ninject控制器工厂等

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

最新文章

  1. 微信小程序把玩(四)应用生命周期
  2. linux中mbr最大多少分区,Linux与磁盘分区介绍(MBR,GPT)
  3. mysql now str,数据库学习之MySQL (十)—— 日期和时间函数 NOW STR_TO_DATE DATE_FORMAT 流程控制函数 IF IFNULL CASE...
  4. mysql存储number_DUMP函数--Oracle是如何在内部存储NUMBER类型的数据?
  5. ng-template 使用过程中参数传递错误的单步调试
  6. oppo 手机侧滑快捷菜单_关于oppo手机菜单键调出的方法,原来是这样的
  7. 李德玉(1965-),男,博士,山西大学计算机与信息技术学院教授
  8. 面试题55 - I. 二叉树的深度
  9. 2017.10.22 方格染色 失败总结
  10. 2012年8月20日 我单身了!
  11. 爆肝100天,B站UP主开发会写高考作文的AI,内含17亿参数、2亿数据、1万行代码
  12. Event-triggered MPC Design for Distributed Systems With Network Communications
  13. python数据结构与算法 20 递归和递归三定律
  14. 201819101025王涵月
  15. 高版本Ubuntu(如22.02)修改apt源,快速安装低版本gcc/g++
  16. 深度学习下运维日志分析的趋势解读与应用实践
  17. java数据类型(java数据类型有哪些)
  18. CentOS7.5安装Oracle19c
  19. dts 编译过程_linux设备树dts移植详解
  20. android note4 android版本,三星Galaxy Note4手机系统是什么?能升级安卓4.3吗?

热门文章

  1. 多元微积分_如何参数化实现绘制甜甜圈
  2. python+selenium环境安装及配置
  3. 2021年GitHub上那些优秀Android开源库总结,全套教学资料
  4. 关于Office2010与Office2016的共存问题
  5. 解决libresource_retriever.so:对‘curl_easy_init@CURL_OPENSSL_3’未定义的引用 ,undefined reference to `uuid_gene
  6. Python基础--Python简介和入门
  7. SQL注入-HTTP头部注入
  8. 苹果怎么应用分身_荣获苹果设计大奖,这款人人称赞的 ToDo 应用究竟应该怎么用?...
  9. 抖音直播间只有高清和标清是怎么设置的?抖音怎么卡高清
  10. dill版本的版本号不一致