天天看点

【机房收费系统】——DataTable和泛型转换

       上一篇博客分析了什么是泛型,以及使用泛型带来的好处。一是提高程序的类型安全,二是取消了装箱和拆箱过程,使性能得到提高。三层架构中,D层负责与数据库交互,一般得到的都是DataTable或DateSet。机房收费系统中,当你通过D层从数据库中取出数据时,是用DataTable来接收的,DataTable就是临时保存数据的虚拟表,你可以从中取出你想要的数据,通过dt.Rows[0][“xxx”];或者dt.Rows[0][1]方式。

       实体类和DataTable的比较

       但是就是因为这样,问题来了,如果返回DataTable,那么层与层之间传递的就不再是实体类,这样就违背了面向对象的思想,也破坏了三层架构。使用DataTable的缺点就不言而喻了:

       1、如果要取得DataTable中的值,需要得到对应字段的下标值。并且编译器不检查,一旦出错,不易找出。

       2、必须了解数据库的结构才能取出字段的值。

       3、不符合面向对象的思想,在分层合作开发时每一层的开发人员都必须了解数据库的结构。

       4、DataTable为弱类型,无法直观看出字段的类型属性。

       面对这个问题,要如何解决呢?使用DataTable来返回值,那么实体类也就没有用了,这样显然是不行的。这个时候就需要使用强大的泛型集合了。通过将DataTable转换为泛型,与实体相对应,然后通过泛型来取得DataTable中的值。那么这样做有什么好处呢?

       1、不用了解数据库的结构,数据库中的字段都变成泛型List的属性,可以直接引用。

       2、符合面向对象的思想和三层架构,通过返回泛型来调用数据

       3、实体类的属性是强类型,每个字段的类型都是已知的

       DataTable转化为泛型

       这里借用一下别人的图片:(感觉十分经典,直观)

【机房收费系统】——DataTable和泛型转换

       相关代码:

Imports System.Collections.Generic
Imports System.Reflection
Public Class DataTableToList
    '将datatable转换为泛型集合
    Public Shared Function ConverToList(Of T As {New})(ByVal dt As DataTable) As IList(Of T)

        Dim mylist As New List(Of T)         '定义最终返回的集合
        Dim mytype As Type = GetType(T)      '得到实体类的类型名

        Dim dr As DataRow                    '定义行集
        Dim TmpName As String = String.Empty '定义一个临时变量

        '遍历datatable的所有数据行
        For Each dr In dt.Rows
            Dim myT As New T    '定义一个实体类对象
            Dim propertys() As PropertyInfo = myT.GetType().GetProperties() '定义属性集合
            Dim pr As PropertyInfo

            '遍历该对象的所有属性
            For Each pr In propertys
                TmpName = pr.Name   '将属性名称赋值给全局变量

                '检查datatable是否包含此列,列名==对象的属性名

                If (dt.Columns.Contains(TmpName)) Then  '将此属性与datatable的列名比较,查看datatable是否包含此属性

                    '判断此属性是否有setter类
                    If (pr.CanWrite = False) Then   '判断此属性是否可写,如果不可写,跳出此循环

                        Continue For
                    End If

                    Dim value As Object = dr(TmpName)   '定义一个对象的列来保存列的值

                    If (value.ToString <> DBNull.Value.ToString()) Then '判断是否为空,如果非空,则赋给对象的属性

                        pr.SetValue(myT, value, Nothing)    '在运行期间通过反射,动态的访问一个动态的属性

                    End If
                End If
            Next
            mylist.Add(myT) '将myT对象添加到集合
        Next
        Return mylist   '返回实体集合
    End Function
End Class
           

       总结:

       通过DataTable到泛型的转换,让我对泛型的理解加深了,最开始只是知道用DataTable会破坏三层架构,不符合面对象的思想,可是为什么呢?我的理解就是在分层合作的时候,如果返回值为DataTable,那么负责每层的人都要去了解数据库的结构,才能正确的取出数据。相当于直接和数据库打交道。而泛型是强类型,编程人员可以不用了解数据库中数据的类型和位置,直接通过泛型就可以很容易的引用了。目前只能理解到这个程度,如果有不正确的地方,还请大家指出!

继续阅读