刚开始在机房重构中用的最多的是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>
<span style="font-size:18px;"> table = SqlHelper.ExecSelect(sql, CommandType.Text, sqlparam) list = JFDAL.ModelHelper.convertTolist(Of JFEntity.CardEntity)(table)</span>