刚开始在机房重构中用的最多的是Datatable,之前没有开始的时候就听大家一直在说泛型,很好奇这个东西,也很想知道明明用Datatable就可以,为什么非要转成泛型?它到底有什么好处呢?于是,便开始了研究……
Datatable是一个临时保存数据的网格,是一个虚拟表。我们在使用Datatable时,通过D层直接将数据库中的数据选出来,返回到B层和U层,在返回的时候我们要是想显示到窗体,就需要将U层的文本框与这个表中的字段一一对应。如果不小心就会写错,然后数据显示就不对。这样对数据库的耦合性太大,不能保证数据库的安全性。
例如我们的学生查询余额这个功能,如果使用Datatable,则为:
<span style="font-size:18px;">If card.Rows.Count Then
txtClass.Text = card.Rows(0)(5).ToString()
txtName.Text = card.Rows(0)(3).ToString()
txtDepartment.Text = card.Rows(0)(8).ToString()
txtGrass.Text = card.Rows(0)(4).ToString()
txtSex.Text = card.Rows(0)(2).ToString()
txtState.Text = card.Rows(0)(7).ToString()
txtCash.Text = card.Rows(0)(6).ToString()
txtStuNo.Text = card.Rows(0)(1).ToString()
End If </span>
这样做功能可以实现,但是却存在一些不完美之处:
1、 必须了解数据库的结构,破坏了数据库的安全性。
2、 在代码编写过程容易写错,因为我们要用虚拟表中各个字段的编号来进行对应,而且这种错误编译器不会进行提示。
3、 在程序中进行数据传递的是Datatable,不再是实体,违背了三层的思想。
Datatable为弱类型,无法直观的看出字段的数据类型。当数据少的时候我们可以一一进行对应,但是如果数据很多的时候Datatable就会有很多想不到的麻烦。所以我们将Datatable转换为泛型。
泛型是具有占位符(类型参数)的类、结构、接口和方法,这些占位符是类、结构、接口和方法所存储或使用的一个或多个类型的占位符。泛型集合类可以将类型参数用作它所存储的队形的类型的占位符;类型参数作为其字段的类型及其方法的参数类型出现。
那么泛型有什么好处呢?
1、 减少输入,传输时只需要传一个实例T就可以获取它的任何属性,便利方便,取到的都是单个的对象。
2、 正确的构建泛型类可以真正的减少代码中的安全性问题。
3、 使用泛型类还可以提高性能。
Datatable转换为泛型的核心思想图:
实体就是数据库中表的映射,因为实体中的每个属性都和数据库表中的字段相对应。Datatable中的每一行记录视为一个实体类,把其中的字段读取出来,存放到实体类的属性中,再把所有的实体类都存放到泛型集合中,因此,Datatable中有多少条记录,泛型集合中就有多少个实体。
那具体Datatable是怎么转化成泛型的呢?
<span style="font-size:18px;">Imports System.Collections.Generic ' 添加泛型集合的命名空间
Imports System.Reflection '添加反射
'/*****************************************
'类 名 称:ModelHelper
'命名空间:JFDAL
'创建时间:2015/7/13 11:31:37
'作 者:邢玉
'小 组:
'修改时间:
'修 改 人:
'版 本 号:v1.0.0
'******************************************
'实现datatable转换成泛型的功能
Public Class ModelHelper
Public Shared Function convertTolist(Of T As {New})(ByVal dt As DataTable) As IList(Of T)
'获得T的类型
Dim type As Type = GetType(T)
Dim ts As New List(Of T)
'定义一个临时变量
Dim strTemp As String = String.Empty
'遍历表中所有行数
For Each dr As DataRow In dt.Rows
'定义类型变量Act获取动态创建对象T的类型
Dim act As T = If((Nothing Is Nothing), Activator.CreateInstance(Of T)(), Nothing)
'引用反射表示可获得对象的所有属性组成的集合
Dim propertys As PropertyInfo() = act.[GetType]().GetProperties()
'定义array变量,接收propertys中含有的属性,并提供对属性propertys元数据访问
Dim array As PropertyInfo() = propertys
Dim intCount As Integer = 0
'遍历所有对象属性
While intCount < array.Length 'length 表示所有维数中元素的总和
'pr表示元素中含有的属性,并提供对数据访问
Dim pr As PropertyInfo = array(intCount)
strTemp = pr.Name
'列名=对象的属性名
If dt.Columns.Contains(strTemp) Then
'判断此属性是否设置函数
If pr.CanWrite Then '该属性是否可写
Dim value As Object = dr(strTemp)
'如果非空,则赋值给对象的属性
If value IsNot DBNull.Value Then
'设这对象的属性值
pr.SetValue(act, value, Nothing)
End If
End If
End If
intCount += 1
Continue While
End While
'添加对象到泛型集合中
ts.Add(act)
Next
Return ts
End Function
End Class
</span>
然后在D层返回Datatable之后加一句调用这个方法的代码就可以了。
<span style="font-size:18px;"> table = SqlHelper.ExecSelect(sql, CommandType.Text, sqlparam)
list = JFDAL.ModelHelper.convertTolist(Of JFEntity.CardEntity)(table)</span>
总结:刚开始使用Datatable时也是可以满足我们的,但是到了后面不能满足我们了,我们就会进行新的探索,然后了解并使用泛型。这就是我们不将就的精神!