机房收费系统重构——Datatable转泛型

        刚开始在机房重构中用的最多的是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转泛型_第1张图片

        实体就是数据库中表的映射,因为实体中的每个属性都和数据库表中的字段相对应。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时也是可以满足我们的,但是到了后面不能满足我们了,我们就会进行新的探索,然后了解并使用泛型。这就是我们不将就的精神!

你可能感兴趣的:(机房收费系统重构——Datatable转泛型)