2.1 使用DataSet构建3层结构
开发3层结构利用系统时,在表示层、业务逻辑层、数据访问层各层中如何使用DataSet呢?DataSet在3层结构中的层次以下图所示:
从图中可以看出,在3层结构中,DataSet的构建和解析工作主要在表示层、数据访问层完成,业务逻辑层主要对DataSet中的数据进行加工、处理和传递。简单地说,DataSet是全部3层结构中数据传递的介质。
2.2 3层结构中DataSet的使用
2.2.1 在表示层中使用DataSet
在表示层中使用DataSet需要做两件事。
(1)将DataSet中的数据展现给用户。
在Winform窗体控件中,DataGridView(数据表格)控件、ComboBox(下拉列表)控件等,他们都有1个数据源属性(DataSource),1般我们可以将Dataset或DataTable绑定到DataSource属性上便可实现数据展现。
(2)将用户的要求数据填充到DataSet中。
要将用户的要求数据填充到DataSet中,我们首先需要构建1个结构与用户要求数据结构相同的DataTable,然后将用户的要求数据填充到构建好的DataTable中,最后将DataTable添加到DataSet中。
表示层的DataSet如图2.3所示。
完成将DataSet中的数据展现给用户和将用户的要求数据填充到DataSet中的具体实现进程将在下面的综合示例中具体演示。
2.2.2 在业务逻辑中使用DataSet
在业务逻辑层使用DataSet需要做下面几件事:
(1)将接收的DataSet传递到下1层。
当业务逻辑层收到数据访问层返回的DataSet后接着将DataSet传递给表示层,或是将表示层要求的DataSet传递给数据访问层。
(2)根据用户要求对DataSet中的数据进行处理。
当业务逻辑层收到要求或响应的DataSet后,根据用户的要求(例如:条件挑选数据)或业务规则会对DataSet中的数据进行处理。
业务逻辑层的DataSet以下图所示:
2.2.3 在数据访问层中使用DataSet
在数据访问层中使用DataSet
在数据访问层中使用DataSet需要做以下事情:
(1)将数据库中的数据填充到DataSet中。
当用户的要求时查询要求时,数据访问层需要实现对数据库的查询访问,并将响应结果填充到DataSet中。
(2)将DataSet中的数据保存到数据库中。
当用户的要求时数据保存要求时,数据访问层首先对收到的DataSet进行解析,然后将解析出的数据保存到数据库中。
数据访问层的DataSet以下图所示:
从上面的讨论中,我们发现DataSet在3层结构的每层中都扮演侧重要的数据载体角色,而每层中基本上都包括了创建DataSet、填充数据、传递DataSet,从DataSet中提取数据等几个步骤。
2.3 如何创建DataSet
DataSet的构建有两种方法。
(1)通过DataAdapter(数据适配器)的Fill方法将数据直接填充到DataSet中。
(2)通过手动编码自定义DataTable(数据表)、DataColumn(数据列)、DataRow(数据行),然后将数据表添加到DataSet中。
首先,我们对DataSet做1个回顾,1个DataSet是由多个DataTable组成,而1个DataTable又是由多个DataColumn和多个DataRow组成。
接下来,我们来分别对DataTable、DataColumn、DataRow进行深入讨论。
1. DataTable
DataTable是内存中的1个关系数据表,可以独立创建使用,也能够作为DataSet的1个成员使用。如何将DataTable作为DataSet的1个成员使用呢?首先,我们需要创建1个DataTable对象,其次通过使用Add方法将其添加到DataSet对象的Tables集合中,以下所示:
DataSet dsClass=newDataSet();
DataTable dtClass=newDataTable("Class");
dsClass.Tables.Add(dtClass);
如果我们没有指定DataTable名称时把DataTable添加到DataSet中,该表会得到1个从“0”开始递增的默许表名(例:Table0、Table1、Table2).
2. DataColumn
DataColumn是创建DataTable的基础,我们通过向DataTable中添加1个或多个DataColumn对象来定义DataTable的结构。DataColumn有1些经常使用属性用于对输入数据的限制,例如:数据类型、数据长度、默许值等,见下表:
属 性 |
说 明 |
AllowDBNull |
是不是允许空值 |
ColumnName |
DataColumn的名称 |
DataType |
存储的数据类型 |
MaxLength |
获得或设置文本列的最大长度 |
DefaultValue |
默许值 |
Table |
所属的DataTable的名称 |
Unique |
DataColumn的值是不是唯1 |
定义DataColumn有两种方法,分别为示例1、示例2:
示例1:
DataColumnclassName=new DataColumn();
className.ColumnName= "ClassName";
className.DataType=System.Type.GetType("System.String");
className.MaxLength=50;
示例2:
DataColumn className=newDataColumn("ClassName",typeof(string));
className.MaxLength=50;
3. DataRow
DataRow表示DataTable中包括的实际数据,我们可以通过DataRow将数据添加到用DataColumn定义好的DataTable中,如示例3所示:
DataColumn className=newDataColumn("ClassName",typeof(string));
className.MaxLength=50;
//创建1个新的数据行
DataRowdrClass=dtClass.NewRow();
drClass["className"]=this.txtClassName.Text.Trim();
2.4 如何自定义DataSet
自定义DataSet主要步骤以下:
①、 创建DataSet对象。
②、 创建DataTable对象。
③、 创建DataColumn对象构建表结构。
④、 将创建好的表结构添加到表中。
⑤、 创建DataRow对象新增数据。
⑥、 将数据插入到表中。
⑦、 将表添加到DataSet中。
示例以下:
DataSet dsClass=newDataSet();
//创建班级表
DataTable dtClass=newDataTable("Class");
//创建年级ID列
DataColumndcClassName=new DataColumn("ClassName",typeof(string));
className.MaxLength=50;
//创建年级ID列
DataColumndcGradeId=new DataColumn("GradeId",typeof(int));
//将定义好列添加到班级表中
dtClass.Columns.Add(dcClassName);
dtClass.Columns.Add(dcGradeID);
//创建1个新的数据行
DataRowdrClass=dtClass.NewRow();
drClass["className"]=this.txtClassName.Text.Trim();
drClass["gradeID"]=objGrade.GetGradeIDByGradeName(this.cboGrade.Text.Trim());
//将新的数据行插入到班级表中
dtClass.Rows.Add(drClass);
//将班级表添加到DataSet中
dsClass.Tables.Add(dtClass);
如上所述,我们学习了如何构建DataSet和如何将数据填充到DataSet中。
2.5 如何获得DataSet中的数据
从DataSet中获得数据有两种方式:
(1)通过指定DataSet中的具体DataTable的某行某列来获得数据。
步骤以下:
①、 通过表名,从DataSet中获得指定的DataTable。
②、 通过索引,从DataTable中获得指定的DataRow。
③、 通过列名,从DataRow中获得指定列的数据。
以获得班级信息为例:
示例以下:
//得到班级名称
dsClass.Tables["Class"].Rows[0][ "ClassName"];
//得到年级ID
dsClass.Tables["Class"].Rows[0][ "GradeID"];
(2)将DataSet的数据直接绑定到数据控件上。
2.6 实现数据访问层
在第1章的项目基础上,实现对业务逻辑层的完善与修改。
#region Public Methods
///<summary>
///获得所有学员信息
///</summary>
///<returns>所有学员信息数据集</returns>
public DataSet GetAllStudents()
{
DataSet ds=new DataSet();
SqlConnection conn=new SqlConnection(connstring);
SqlDataAdapter objAdapter=new SqlDataAdapter("usp_SelStudentInfo",conn);
//usp_SelStudentInfo 为查找学生存储进程信息
objAdapter.SelectCommand.CommandType=CommandType.StoredProcedure;
objAdapter.Fill(ds,"stuTable");
conn.Close();
conn.Dispose();
return ds;
}
#endregion
//根据年级编号取得班级信息,参考代码以下:
public DataSetGetClassByGradeID(int gradeID)
{
DataSet ds = new DataSet();
SqlConnection conn = new SqlConnection(connString);
SqlDataAdapter objAdapter = newSqlDataAdapter( "usp_SelectClassesByGradeID",conn);
objAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
objAdapter.SelectCommand.Parameters.Add("@GradeID", SqlDbType.Int).Value = gradeID;
objAdapter.Fill(ds, "classTable");
conn.Close();
conn.Dispose();
return ds;
}
/// 根据性别挑选学员信息,并按姓名排序
public DataViewGetStudentBySex(string sex)
{ //实例化DataView对象
DataView dvStudent = new DataView();
//获得从数据层返回的学生信息表
dvStudent.Table = studentController.SelectAllStudent().Tables["studentTable"];
//根据条件过滤信息
if (sex.Trim() == "男")
dvStudent.RowFilter ="Sex='男'";
if (sex.Trim() == "女")
dvStudent.RowFilter ="Sex='女'";
//按学生姓名降序排序
dvStudent.Sort = “StudentName DESC”;
//返回过滤后的数据视图
return dvStudent;
}
//其他代码见上课案例.
【
在用3层架构开发利用程序时,首先根据需求编辑界面数据展现方式,然后按底层到顶层的顺序实现数据访问层、业务逻辑层、表示层。
在实现数据访问层时,为了使我们开发的利用程序易于保护,我们常把不同表的数据访问代码封装在不同的类里,1般情况下1个类对应1张表。
】
小结
n 用Ado.Net实现3层结构利用程序时,DataSet的主要作用是3层之间数据传递的载体。
n 用Ado.Net实现3层结构利用系统时,数据访问层主要使用的类有:
ü SqlConnection类,实现数据库连接。
ü SqlCommand类,履行Sql命令。
ü SqlDataReader类,读取数据。
ü SqlDataAdapter类,履行Sql命令,返回DataSet。
ü DataSet类,封装用户要求数据。
n 用Ado.Net履行带参数的Sql命令时,需要使用参数化类Parameters的Add方法为Sql命令添加参数,包括参数名称、参数类型。结合Ado.Net章节来重新使用参数化对象对数据访问层、业务逻辑层进行重新代码架构。
n 业务逻辑层实现数据传递、处理时,首先援用数据访问层,其次实例化数据访问对象,最后调用数据访问层功能,并实现数据处理。
作业:
完善第1章自己已架构好的MIS系统,丰富完善数据访问层、业务逻辑层和表示层,要求:
1. 利用本章讲授的DataSet进行数据传递;
使用存储进程来操作数据。