个人机房重构的过程中,我们接触到了DataTable和泛型,对于这两种数据类型,各有自己的优缺点,结合机房收费系统中的应用和借鉴的资料,总结整理分享给大家。
DataTable 是一个临时保存数据的网格虚拟表(表示内存中数据的一个表。DataTable是ADO dot net 库中的核心对象。它可以被应用在 VB 和 ASP 上。它无须代码就可以简单的绑定数据库。它具有微软风格的用户界面。
DataTable是一个非常好用的用于临时保存数据的表格的数据类型。对于处理数据量小的系统具有很好的方便性和易用性,由于DataTable保存的数据表一定程度上反映了数据库中数据表的一定样子,使得数据的展现更加直观和高效率。而且与DataGridView控件的结合,充分的展现了它的实用性。
如图:
正如刚才所说,DataTable是一个存储数据的虚拟表,会占用一定的内存,但当数据量无比巨大时,就会导致DataTable的崩溃,致使系统无法正常使用。其次,DataTable读取数据库数据时,必须要了解数据库数据的结构,给编程带来了一定的风险,一旦数据库修改,则意味着系统也必须同时修改,这不符合面向对象的编程思想。而且DataTable为弱类型,无法直观的看出字段的数据类型。
我们结合代码来分析:
'填充文本框 txtStudentNo.Text = dt.Rows(0).Item(2) txtName.Text = dt.Rows(0).Item(3) txtSex.Text = dt.Rows(0).Item(4) txtTie.Text = dt.Rows(0).Item(5) txtGrade.Text = dt.Rows(0).Item(6) txtClass.Text = dt.Rows(0).Item(7) txtStatus.Text = dt.Rows(0).Item(11) txtExplain.Text = dt.Rows(0).Item(9) txtBalance.Text = dt.Rows(0).Item(8)
如上面的代码所示,每个文本框所绑定的是具体的某一行某一列的数据,一对一的绑定关系,一旦修改数据库字段的顺序,就会导致系统显示信息的错误,这更像是面向过程的编程方式。
为实现同样的功能 ,我们看一看使用泛型的代码:
'查询后的显示到窗体上 txtStudentNo.Text = myList(0).StudentNo txtState.Text = myList(0).Status txtBalance.Text = myList(0).Cash txtDepart.Text = myList(0).Department txtGrade.Text = myList(0).Grade txtClass.Text = myList(0).Sclass txtSex.Text = myList(0).Sex txtState.Text = myList(0).Status txtRemark.Text = myList(0).Remark txtName.Text = myList(0).StudentName
'********************************************** ' 文 件 名:ConvertGenericsHelper ' 命名空间:DAL ' 内 容: ' 功 能: 将Datatable转换为泛型 ' 作 者:王洪玉 ' 小 组:王洪玉 ' 生成日期:2016/2/13 20:06:17 ' 版 本 号:V1.0.0.0 ' 修改日志: '********************************************** Imports System.Collections.Generic '增加泛型的命名空间 Imports System.Reflection '引入反射,为了使用PorpertyInfo Public Class ConvertGenericsHelper '将datatable转换为泛型集合 Public Shared Function convertToGenerics(Of T As {New})(ByVal dt As DataTable) As IList(Of T) '注意:这里的New是用来约束T的,必须要有,不然new T的时候会出现错误 Dim myGenerics As New List(Of T) '定义最终返回的集合 Dim myType As Type = GetType(T) '得到实体类的类型名 Dim dr As DataRow '定义行集 Dim tempName As String = String.Empty For Each dr In dt.Rows '遍历DataTable的所有数据行 Dim myT As New T '定义一个实体类的对象 Dim propertys() As PropertyInfo = myT.GetType().GetProperties() '定义属性集合 Dim Pr As PropertyInfo For Each Pr In propertys '遍历该对象的所有属性 tempName = Pr.Name '将属性名称赋值给临时变量 '检查DataTable是否包含此列(列名==对象的属性名) If (dt.Columns.Contains(tempName)) Then '将此属性与dataTable里的列名比较,查看datatable是否包含此属性 '判断此属性是否有Setter If (Pr.CanWrite = False) Then '判断此属性是否可写,如果不可写,跳出本次循环 Continue For End If Dim value As Object = dr(tempName) '定义一个对象型的变量来保存列的值 If (value.ToString <> DBNull.Value.ToString()) Then '如果非空,则赋给对象的属性 Pr.SetValue(myT, value, Nothing) '在运行期间,通过反射,动态的访问一个对象的属性 End If End If Next myGenerics.Add(myT) '添加到集合 Next Return myGenerics '返回实体集合 End Function End Class
'先判断dt是否为空 If dt.Rows.Count > 0 Then '将dt转换为泛型集合 myList = ConvertGenericsHelper.convertToGenerics(Of Entity.EN_StudentInfo)(dt) Return myList Else Return Nothing End If
dgvLine.DataSource = dtcard '将dtcard的值传给DataGridView控件 dgvLine.Columns(0).HeaderText = "卡号" '显示表头 dgvLine.Columns(1).HeaderText = "充值金额" dgvLine.Columns(2).HeaderText = "充值日期" dgvLine.Columns(3).HeaderText = "充值时间" dgvLine.Columns(4).HeaderText = "充值教师"
DataGridView.Rows.Add(MyList.Count) '数据表添加行,行数等于数据行数 For i = 0 To QueryDate.Count - 1 '变量写入行上的每个数据,rows代表行,Cell代表第几个格 DataGridView.Rows(i).Cells(0).Value() = MyList(i).CardNo DataGridView.Rows(i).Cells(1).Value() = MyList(i).RechargeCash DataGridView.Rows(i).Cells(2).Value() = Format(MyList(i).RechargeDate) DataGridView.Rows(i).Cells(3).Value() = MyList(i).RechargeTime DataGridView.Rows(i).Cells(4).Value() = MyList(i).UserID DataGridView.Rows(i).Cells(5).Value() = MyList(i).IsCheck Next