1)三层框架是什么?
按照书籍和博客文章里千篇一律的解释就是:UI层、BLL层、DAL层。这样的解释通常无法让人一时半会理解含义,总而言之在这里先大概说明一下三层架构。正如其他文章提到的一样,三层架构就是:表示层(与用户直接进行交互)、业务逻辑层(在表示层和数据访问层中间联系两者的重要角色)、数据访问层(与数据库实打实的做交易,存取数据之类的)。所谓UI层实际上就是跟用户打交道的那一层,比如控制台应用程序、asp.net web应用程序、窗体应用程序,这些项目文件都是用于跟用户打交道的,所以就是UI层。

2)为什么使用三层框架?
假设有一个窗体应用程序,比如新建了一个winform窗体应用。用户单击注册按钮后,将各种数据提交到后台,此时你可以直接调用ExecuteNonQuery()方法并将用户数据写入数据库。而三层架构的特点就是将用户注册的业务提交给了BLL层,再由BLL层提交给DAL层处理问题,这样用户的注册业务就经过了好几步才完成。为什么要这么麻烦?
有这么一家饭馆,由于刚起步所以只有厨师来管理整个饭馆。他们兼顾给客人点菜、做菜、上桌的事情。日子渐渐过去,饭馆规模将要扩充,这时候考虑雇佣服务员来为客人点单并将菜单交给厨房处理。增加服务员后,客人不会直接与厨师说要什么菜,因为客人变多意味着厨师变忙,而厨师变忙乱或许还会影响正在做的菜。所以客人就可以将菜单交给服务员,而服务员又将菜单交给厨房做菜,等厨房菜做好之后,服务员又将菜交给相应的客人。这样做的好处在于:①让复杂的工作变得有秩序。②其中任意一个环节出了问题,能够更加迅速发现并快速维护。③分工合作使得每个人的工作量变得固定,更加人性化。
代码的分层能让不同职员负责不同的层,通过分层能将业务细节分解,将不同功能的代码分散出来。这样做更加有利于系统的开发,业务越大可能分的层也越多,都是为了让系统便于维护和扩展。从另一方面讲,分工合作的优势就是让适合的人做自己擅长的事情,使得平均劳动时间变短,让效率变高。 软件的分层实际上就是实现“高内聚、低耦合”。就以上面的【用户单击注册按钮】的例子来讲,所有的包括业务逻辑、数据库操作用到的方法甚至sql语句都存在一个Form1类里面,这就必须使得做这个项目的人不但要会业务逻辑,还要懂数据库操作。如果分为三层来操作,那么UI层的编码人员不需要懂sql语句,它只要知道调用一个别人写好的方法就可以获得自己需要的东西就可以了,这样结构更加清晰,分工更明确。

3)如何使用三层架构?
以一个从数据库查询表并返回到窗体上的例子来解释,只要清楚了这个查询怎么实现,其他的增删改查也用同样的套路完成。
第1步,本次实验使用SQLserver。先设计好数据库,新建表Student并添加一些记录,表字段如下:

第2步,新建Model类库文件,虽然Models不在三层架构的概念说明里(UL、BLL、DAL),但却是开发必要的。Models提供实体类,贯穿整个项目,三层都需要用到它。在解决方案上右键-添加-新建项目-类库,名字叫Student.Model。在类库文件下新建实体类,名字是Students.cs,为了节省篇幅这里使用自动属性,代码如下:

public class Students  {  public string Address { get; set; }  public int? Weight { get; set; }  public int? Tall { get; set; }  public string Gender { get; set; }  public string Birthday { get; set; }  public string Name { get; set; }  public int Id { get; set; }  }

第3步,按照添加Model类库文件的做法添加一个DAL类库文件,名字叫Student.DAL。因为上面提到过实体类贯穿三层,因此DAL层要添加对Model的引用,在。在类库文件下新建SQLHelper类用于实现数据库操作,新建StudentDAL类用于接收来自BLL层的增删改查处理。
第4步,新建类库文件(DAL层),取名叫Student.DAL,上面提到过实体类贯穿整个项目,因此DAL层要添加对Student.Model的引用。在“引用”上右键-添加引用-解决方案,找到Student.Model并勾选确定。然后在DAL类库文件下新建StudentDAL类和SqlHelper类。StudentDAL类主要提供业务处理需要用到的方法,比如查询表,比如根据Id查找用户,比如删除用户等等……这里只提供查询表的方法。SqlHelper类主要是对数据库实际进行查询操作需要用到的方法。详细代码如下
StudentDAL类代码(注意先using Student.Model;):

public class StudentDAL{public DataTable Select(){DataTable table = SqlHelper.ExecuteQuery("select * from Student");return table;}}

SqlHelper类代码:

class SqlHelper{private static readonly string connStr = ConfigurationManager.ConnectionStrings["testConn"].ConnectionString;public static SqlConnection createConnection(){SqlConnection conn = new SqlConnection(connStr);conn.Open();return conn;}//执行查询:select返回多行多列public static DataTable ExecuteQuery(SqlConnection conn, string sql, params SqlParameter[] parameters){DataTable table = new DataTable();using (SqlCommand cmd = conn.CreateCommand()){cmd.CommandText = sql;cmd.Parameters.AddRange(parameters);using (SqlDataReader reader = cmd.ExecuteReader()){table.Load(reader);}}return table;//返回加载的表}public static DataTable ExecuteQuery(string sql, params SqlParameter[] parameters){using (SqlConnection conn = createConnection()){return ExecuteQuery(conn, sql, parameters);}}}

注意:SqlHelper类中的ExecuteQuery()方法构成重载,主要是方便DAL层调用这个方法时少传入一个SQLConnection对象的参数,这些都在SqlHelper类内部进行处理并自动调用真正实现查询操作的方法来处理数据了。
第5步,新建类库文件(BLL层),取名叫Student.BLL。BLL层需要将任务提交给DAL层处理,并且上面提到过实体类贯穿整个项目,因此BLL层要添加对DAL层和Model的引用,参照上面的方式,添加对Student.DAL和Student.Model的引用。在BLL类库文件下新建StudentBLL类,详细代码如下
StudentBLL类的代码(注意先using Student.Model;和using Student.DAL;):

public class StudentBLL{private StudentDAL sDal = new StudentDAL();public DataTable Select(){return sDal.Select();}}

第6步,新建winform窗体应用,这表示UI层。假设名字叫Student.Winform。先using Student.BLL;,然后在窗体上添加一个DataGridView控件,图片如下:

第7步,在Student.Winform窗体应用程序下的App.config里配置数据库连接字符串,在 <configuration>标签里配置如下代码:
<connectionStrings>
    <add name="testConn" connectionString="server=.;database=CRUDTest;uid=sa;pwd=145217"/>
  </connectionStrings>
其中name属性的值与DAL层下SqlHelper类中的ConnectionStrings["testConn"]保持一致。server表示数据库地址,小数点代表本地地址。database表示数据库名字。uid是数据库登录用户名。pwd是数据库登录密码。
接着添加窗体应用程序的代码,主要添加一个Load事件,详细代码如下:

public partial class Form1 : Form{public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){StudentBLL bll = new StudentBLL();DataTable table = bll.Select();dataGridView1.DataSource = table;}}

第8步,将Student.Winform设为启动项并运行程序,如果能观察到运行结果则说明没有问题。

4)对上面代码执行过程做解释
1.运行窗体程序会自动执行Load事件的代码,先声明StudentBLL类的对象,然后就可以调用BLL层的Select()方法。
2.BLL层会先声明StudentDAL类的对象,然后继续调用DAL层的Select()方法。BLL层并不实现查询操作,只是将这个任务交给DAL层处理了。
3.DAL层的Select()方法会调用SqlHelper类的ExecuteQuery()方法。在SqlHelper类内部又会先调用写好的获得一个SQLConnection对象的方法,并调用构成重载的另一个ExecuteQuery()方法。
4.构成重载的这个ExecuteQuery()是具体实现数据库操作的方法,查询到表结果后逐步返回到DAL层的Select()方法里。
5.DAL层的Select()方法已经获得调用ExecuteQuery()方法返回的表结果,并将这个表结果返回到调用它的BLL层里。BLL层又将表结果返回到调用BLL层的UI层里。
6.UI层里执行dataGridView1.DataSource = table;用于将表数据填充到控件上显示。至此完成表数据查询操作。

5)三层架构的概念补充
1.参照上面对三层架构的讲解与练习,实际上可以用一张图片来解释上面的运行过程。理解三层架构的含义后,甚至用这张图解释上面提到的餐馆例子也可以。UI层相当于客户,BLL层相当于服务员,而DAL层相当于厨师。

2.有代码生成器可以自动生成三层架构的项目,甚至连数据库增删改查方法都提供了。比如“动软代码生成器”,当然不要太依赖软件的“自动”。

3.或许在做了上面三层架构的练习后,会觉得BLL层的功能微乎其微。实际上在BLL层可以进行逻辑判断,这也正是BLL层的好处所在。比如BLL层拿到DAL层返回过来的数据后,可以进行相应的if判断,确保数据满足业务需求,再返回给UI层。

C#回顾学习笔记四十:三层架构相关推荐

  1. JSP学习笔记(四十九):抛弃POI,使用iText生成Word文档

    POI操作excel的确很优秀,操作word的功能却不敢令人恭维.我们可以利用iText生成rtf文档,扩展名使用doc即可. 使用iText生成rtf,除了iText的包外,还需要额外的一个支持rt ...

  2. 拉勾网《32个Java面试必考点》学习笔记之十二------架构演进与容器技术

    本文为拉勾网<32个Java面试必考点>学习笔记.只是对视频内容进行简单整理,详细内容还请自行观看视频<32个Java面试必考点>.若本文侵犯了相关所有者的权益,请联系:txz ...

  3. Android学习笔记四十Preference使用

    Preference直译为偏好,博友建议翻译为首选项.一些配置数据,一些我们上次点击选择的内容,我们希望在下次应用调起的时候依旧有效,无须用户再一次进行配置或选择.Android提供preferenc ...

  4. windows内核开发学习笔记四十四:注册表存储结构-储巢

    上一篇文章学习了注册表的逻辑结构,接下来我这篇文章来学习注册表的存储结构.注册表实际存储是由一组储巢构成,每个储巢包含了一个由键和值构成的层次结构.下面表是windows的各个储巢的注册表路径和文件路 ...

  5. JAVA学习笔记(四十九)- Swing相关组件

    JFrame组件 import java.awt.Color;import javax.swing.JFrame; import javax.swing.JPanel;/** Swing是在AWT基础 ...

  6. JavaScript学习笔记(四十四) 装饰器

    装饰器模式(Decorator) 在装饰器模式中,可以在运行时给一个对象动态的添加额外的功能.当和静态类打交道的时候(static classes),这可能是一个挑战.但在JavaScript中,对象 ...

  7. Swift学习笔记 (四十二) 不透明类型

    具有不透明返回类型的函数或方法会隐藏返回值的类型信息.函数不再提供具体的类型作为返回类型,⽽是根据它支持的协议来 描述返回值.在处理模块和调用代码之间的关系时,隐藏类型信息⾮常有用,因为返回的底层数据 ...

  8. java从入门到精通二十四(三层架构完成增删改查)

    java从入门到精通二十四(三层架构完成增删改查) 前言 环境准备 创建web项目结构 导入依赖和配置文件 创建层次模型 实现查询 实现添加 实现修改 完成删除 做一个用户登录验证 会话技术 cook ...

  9. Windows保护模式学习笔记(十四)—— 阶段测试

    Windows保护模式学习笔记(十四)-- 阶段测试 题目一 解题步骤 题目二 解题步骤 题目一 描述:给定一个线性地址,和长度,读取内容 int ReadMemory(OUT BYTE* buffe ...

最新文章

  1. 【python3】 抓取异常信息try/except
  2. 高通APQ8074 spi 接口配置
  3. c语言深入浅出(一)strcpy和memcpy的区别
  4. Google AdWords广告的12个技巧
  5. 如何把数据库从sql变成mysql_(转)如何将数据库从SQL Server迁移到MySQL
  6. oracle——监听(二、sqlplus连接数据库)
  7. dojo——AMD(二、AMD中class内部成员函数相互调用实现)
  8. Windows核心编程_修改U盘图标
  9. Rust:字符串数组的拼接、与 String 、 str的选择
  10. Sublime Text, MikTeX (或TeXLive), SumatraPDF 配置LaTeX开发环境
  11. Deep Learning 学习笔记
  12. 快速JD获取eid和fp
  13. matlab俄罗斯方块
  14. Hadoop Yarn 安装
  15. pe装kali linux,二、整合老毛桃PE + Kali Linux
  16. 【总结】本地springboot连接腾讯云Redis
  17. Windows下 mysql定时备份
  18. python程序在嵌入式linux系统运行。。
  19. ipv6地址概述——了解ipv6地址
  20. Linux Redis清理缓存

热门文章

  1. java学习路线规划
  2. samba更改其他端口,如何与windows共享文件夹
  3. 怎么用计算机按反三角函数的导数,反三角函数求导过程
  4. 输入一个字符串转换成十进制整数
  5. python批量提取word指定内容_python批量提取word内信息
  6. apollo github的说明介绍
  7. 乾宏教育海南省中高级工程师职称评审
  8. wget OpenSSL: error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version
  9. MinGW中的头文件路径
  10. 大连软件知名公司最新职位