三层:表示层:1.数据展示(显示数据)。2.接收数据。
用于显示数据 和 接收用户输入的数据,为用户提供一种交互式操作界面。(一般为Windows应用程序或Web应用程序)
业务逻辑层:1.业务逻辑处理。2.数据传递。
是表层和数据访问层之间通信的桥梁,
主要负责 数据的传递和处理。
(1.规则对数据进行加工和处理。
2.与相邻的表示层和数据库访问层进行数据交换。)
数据访问层:主要实现对数据的保存和读取操作。
数据访问,可以访问关系数据库、本文件或是XML文档等。数据访问层通常为类库。
二层结构的局限性:1. 难以适应需求变化。
2. 不易维护。
3. 安全性低。
三层之间的依赖关系:表示层 依赖 业务逻辑层。业务逻辑层 依赖 数据访问层。
表示层只允许引用业务逻辑层,不允许直接引用数据访问层。
各层项目间不允许循环引用。
1. 接收用户的请求,根据用户的请求去通知业务逻辑层;业务逻辑层收到请求,首先对请求进行阅读审核,然后将请求通知数据库访问层或直接返回给表示层;数据访问层收到请求后便开始访问数据库。
2. 数据访问层通过对数据库的访问得到请求的结果,并把请求结果通知业务逻辑层;业务逻辑层收到请求结果,首先对请求结果进行阅读审核,然后将请求结果通知表示层;表示层收到请求结果,并将结果展示给用户。
搭建三层结构基本框架的步骤:1. 搭建表示层。
2. 搭建业务逻辑层。
3. 搭建数据访问层。
4. 添加各层之间的相互依赖。
第 2 章: 用ADO.NET实现三层结构
DataSet:在内存中存在的临时数据库。
(表的集合(列,行,约束)以及表之间的关系的集合)
DataSet的主要作用:三层之间数据传递的载体。
在三层结构中,DataSet的构建与解析工作主要在表示层、数据访问层,业务逻辑层主要对DataSet中的数据进行加工、处理和传递。(DataSet是整个三层结构中数据传递的介质)。
1、表示层 使用DataSet需要做的两件事:
(1)将DataSet中的数据展示给用户。
一般我们可以直接将DataSet或DataTable绑定到DataSource属性上就可以实现数据展示。
(2)、将用户的请求数据填充到DataSet中。
2、业务逻辑层 使用DataSet需要做的两件事:
(1)、将接收到的DataSet传递到下一层。
当业务逻辑层收到数据访问层返回的DataSet 后接着将DataSet 传递给表示层,或者是 将表示层请求的DataSet传递给数据访问层。
(2)、根据用户请求对DataSet中的数据进行处理。
当业务逻辑层收到请求或响应的DataSet后,根据用户的请求(例如:条件筛选数据)或业务规则会对DataSet中的数据进行处理。
3、数据访问层 使用DataSet需要做的两件事:
(1)、将数据库中的数据填充到DataSet中。
当用户的请求是查询请求时,数据访问层需要实现对数据库的查询访问,并将响应结果填充到DataSet中。
(2)、将DataSet中的数据保存到数据库中。
当用户的请求是数据保存时,数据访问层首先对收到的DataSet 进行解析,然后将解析出的数据保存到数据库中。
每层中基本上包括了:1.创建DataSet 。
2.填充数据。
3.传递DataSet。
4.从DataSet中提取数据。
数据访问层主要使用的类:1. SqlConnection类:实现数据库连接。
2. SqlCommand类:执行SQL命令。
3. SqlDataReader类:读取数据。
4. SqlDataAdapter类:执行SQL命令,返回DataSet。
5. DataSet类:封装用户请求数据。
DataSet的构建有两种方法:
1. 通过DataAdapter(数据适配器)的Fill 方法将数据直接填充到DataSet 中。
2. 通过手动编码自定义DataTable(数据表)、DataColumn(数据列)、DataRow(数据行),
然后将数据表添加到DataSet中。
一个DataSet是由多个DataTable组成,而一个DataTable又是由多个DataColumn和多个DataRow组成 。
(1)、DataTable(数据表):是内存中的一个关系数据表,可以独立创建使用,也可以作为DataSet的一个成员使用。(指定表名时一定要避免表名重复)。
(2)、DataColumn(数据列):是创建DataTable 的基础,我们通过向DataTable中添加一个或多个DataColumn对象来定义DataTable的结构。
DataColumn的常用属性:
属 性 |
说 明 |
AllowDBNull |
是否允许空值 |
ColumnName |
DataColumn的名称 |
DataType |
存储的数据类型 |
MaxLength |
获取或设置文本列的最大长度 |
DefaultValue |
默认值 |
Table |
所属的DataTable的名称 |
Unique |
DataColumn的值是否唯一 |
定义DataColumn有三种方法:
1. object obj = new object();
obj.GetType
缺点:必须实例化对象,才能获得。
2. (“字段名”,typeof(string));
3. Type.GetType(”System.String”);
最为灵活(反射:动态获取不同类型的信息)。
(3)、DataRow(数据行)
DataRow表示DataTable中包含的实际数据,我们可以通过DataRow将数据添加到用DataColumn定义好的DataTable中。
自定义DataSet的主要步骤:1.创建DataSet对象。
2.创建DataTable对象。
3.创建DataColumn对象构建表结构。
4.将创建好的表结构添加到表中。
5.创建DataRow对象新增数据。
6.将数据插入到表中。
7.将表添加到DataSet中。
从DataSet中获取数据有两种方法:
1、通过指定的DataSet中的具体DataTable的某行某列来获取数据。
(1)通过表名,从DataSet中获取指定的DataTable。
(2)通过索引,从DataTable中获取指定的DataRow。
(3)通过列名,从DataRow中获取指定列的数据。
2、将DataSet中的数据直接绑定到数据展示控件上。
DataView:为我们提供DataTable的动态视图,并可以对动态生成的视图中的数据进行排序筛选等操作。
一个DataSet中可以有多个DataTable,一个DataTable可以动态生成多个DataView。
(DataSet中包含DataTable,DataTable中包含DataView)
DataView的常用属性:
属 性 |
说 明 |
Table |
用于获取或设置源DataTable。 |
Sort |
获取或设置DataView的一个或多个排序列以及排序顺序。 |
RowFilter |
获取或设置用于筛选在DataView中查看哪些行的表达式。 |
Count |
在应用RowFilter后,获取DataView中的行数。 |
用ADO.NET执行带参数的SQL命令时,我们需要使用参数(Parameters)集合的Add方法为SQL命令添加参数,包括参数名称、参数类型。
业务逻辑层实现数据传递、处理时,首先引用数据访问层,其次实例化数据访问对象,最后调用数据访问层功能,并实现数据处理。
第 3 章: 用OOP实现三层结构
使用DataSet开发三层结构有哪些局限性:
(1) DataSet不具备良好的面向对象(OO)特性,使用起来不够直观、方便。
(2) 对DataSet中的数据进行查找时容易出错。
(3) 由于DataSet的核心结构与数据库的核心结构完全相同,所以它把数据结构完全暴露在表示层和业务逻辑层。
使用实体类的主要好处有一个简单的事实,即实体类是完全受我们控制的对象,它具有面向对象的基本特征。
其实和DataSet一样,业务实体也承载着一个数据载体的任务。
实体类是业务对象的基础,它用面向对象的思考为我们消除了关系数据库与对象之间的差异。
实体类:描述一个业务实体的”类”(整个应用系统业务所涉及的对象)。
业务实体 可以认为属于 业务逻辑层。也可以将业务实体单独作为一层称为 业务实体层。
表示层、业务逻辑层、数据访问层都依赖于业务实体,各层之间数据的传递主要是实体对象(业务信息封装在实体对象中)。
在 表示层 使用实体类需要做的两件事:
1. 将解析实体对象中封装的数据展示给用户。
当表示层接收到从业务逻辑层返回的实体对象,并将实体对象中封装的信息展示给用户时,表示层需要对实体对象中封装的信息进行解析。
表示层对实体对象的解析分为两种:
(1) 对单个实体对象进行解析:每个实体对象中封装的数据对应数据表中的一条记录。
(2)对实体对象集合进行解析:将多个实体对象封装到List
2. 将用户请求的数据封装到实体对象中。
在表示层,我们如何将用户的请求的数据封装到实体对象中,我们首先需要实例化实体对象,然后将用户的请求数据赋值给实体对象中的对应的属性。
业务逻辑层 实体类的使用不同于表示层,它主要负责传递实体对象,并对实体对象中封装的数据进行处理。它同样需要做两件事:
1. 将接收到的实体对象传递给下一层。
当业务逻辑层接收到装有信息的业务实体对象后,根据请求或响应将实体对象传到下一层。
2. 根据用户的请求对实体对象中的数据进行处理。
(1)一方面来自业务实体对数据的处理,实体类本身是由属性组成的,而大多都是可读写属性。所以根据请求的不同可以给属性设置不同的值。
(2)另一方面来自业务逻辑对数据的处理。
在数据访问层使用实体类需要做两件事:
1. 将数据库中的数据封装到实体对象中或将多个实体对象封装成集合。
当用户的请求数据是数据查询请求时,数据访问层需要实现对数据库的查询访问。
当请求的结果只有一条记录时,我们将这条记录封装成一个实体对象。
当请求的结果是多条记录时,我们将每条记录封装成一个实体对象,然后再将多个实体对象封装成集合(将多个实体对象封装到List
2. 将实体对象中的数据保存到数据库中。
当用户的请求是数据保存请求时,数据访问层首先对实体类中封装的数据进行分析,
然后将解析出的数据保存到数据库中。
使用实体类的好处:为我们整个项目的开发提供了很大的灵活性。
它把数据库中的表用面向对象的思想抽象成类,使数据作为对象来使用,消除了关系数
库与类之间的差别,在三层结构开发中使用实体类更有助于项目的维护、扩展、更体现
三层结构开发的优势。
(在数据库中添加一个字段时,只需在实体层中添加一个字段,封装,再修改SQL语句)
根据数据表编写实体类时,需注意的:
1. 表中的每个字段,对应实体类中的一个protected类型的字段和一个public类型的属性。
2. 表中字段的类型要与属性的类型相匹配。
(数据库中的varchar、nvarchar类型对应C#中的String类型)
3. 在我们编写好的实体类前面一般要加上序列化属性[Serializable],它对实体类中的所有字段、属性进行序列化处理。
序列化的主要目的:为了提高数据传输中的性能与安全性。
Using关键字在C#中的用途:
1. 作为指令,引用命名空间。
2. 作为语句,用于定义一个范围,在此范围末自动释放对象。
Using(SqlConnection conn = new SqlConnection()){}
常用数据访问方法命名规范:
方 法 |
说 明 |
Public int AddSutdent(Student student){} |
学员账户创建 |
public void DeleteStudentByLoginId (string loginID) {} |
根据学员账户ID删除学员信息 |
Public void ModifyStudent (Student student) {} |
更新学员信息方法 |
Public IList |
得到所有学员信息集合 |
Public Student GetStudentByLoginID(string loginID){} |
根据登录ID得到学员信息 |
(配置文件放在表示层内,被数据访问层引用)。
第 4 章: 异常处理与单元测试
“异常”是程序在执行时发生的错误,导致这种错误的原因有三个方面:
1. 代码错误,包括语法错误、逻辑错误,这是由开发人员造成的。
2. 资源不可用,这是由系统访问了未经授权的资源而引起的错误。
3. 公共语言运行库,这是由CLR内部引起的错误。
Exception 类:为我们提供了大量的捕获、处理异常的方法。
Exception 类是所有异常的基类。
Exception 类中封装的异常处理由两种:
1. 由用户程序执行引发的异常,派生于ApplicationException类。
2. 由公共语言运行库引发的异常,派生于SystemException类。
常见异常类型:
Exception类 |
说 明 |
SystemException |
|
ArgumentException |
|
ArithmeticException |
|
DataException |
|
FormatException |
|
IOException |
|
IndexOutOfRangeException |
|
ArgumentNullException |
|
DivideByZeroException |
|
OverflowException |
|
ApplicationException |
|
TargetExcepion |
|
异常类常用属性:
属 性 |
说 明 |
Message |
提供引起异常的详细信息 |
Source |
|
StackTrace |
|
InnerException |
|