三层架构中DataTable华丽变身泛型集合

来源:互联网 发布:淘宝350模板的缺点 编辑:程序博客网 时间:2024/04/29 18:23

前言:

    做系统前期,抱着“实现了三层已经很不错了”的心情,并没有考虑到DataTable传到B层,或传到U层与DataGridView绑定,显示数据有什么错误的地方。后来“偷”听了一节课,才知道返回DataTable是破坏三层结构的。于是就开始了三层架构中DataTable变形记的探索。


    变形之前我考虑到了以下几点内容,也是看了很多的资料,总结下来的。(本身是菜鸟一枚,So...下面展示的代码不是我自己写的,参考了十期师哥的博客。站在巨人肩膀上啦)



一、DataTable与List<>的区别


    DataTable是数据集的填充,List<>是对象化的填充。DataTable是弱类型,没有办法直接看出数据表中字段的数据类型,List<>是强类型。最大的区别是,List<>可以灵活转换,不用装箱和拆箱(装箱拆箱:利用装箱和拆箱功能,可通过允许值类型的任何值与Object 类型的值相互转换),这个过程中可能会造成数据的错误丢失,这样看来DataTabel也不是很安全的。



图一(三层依赖model传数据)


图二(三层依赖DataTable传数据)



    从上面的图中明显看得到,DataTable的出现,使UI,BLL,DAL层都去直接的访问它了,而我们自己写的Model被甩到了一边。这一点就可以看出DataTable破坏了我们的三层结构。那么如果不使用DataTable,问题就来了。一条数据好处理,就实例化一个实体对象就可以了。如果是多个数据呢?那么就引出了我们需要使用的泛型集合了,简单的可以理解为一群实体。





二、为什么使用List<>

回答这个问题,其实就是在回答泛型集合有什么好处?因为它的优点,我们才考虑去使用它。

优点:

  • 减少输入,传输时只需要传一个实例T就可以获取它的任何属性。遍历方便,取到的都是单个的对象。——方便
  • 正确地构建的泛型类可以真正减少代码中的安全性问题。——安全
  • 使用泛型类还可以提高性能。其中最大的一个改进是.NET框架组件不会在值类型上使用包装(boxing)。尽管泛型类可以使用多个数据类型工作,但是它在后台单独地处理每一种数据类型。这种技术确保了在你的工作量最小的情况下,应用程序提供最佳的性能。——效率高

缺点:

  • 在绑定数据时也会产生很多麻烦。——绑定要重新实例化





三、实践变形


    这里我们需要写一个转换的类,让DataTable实现变身:


Imports System.Collections.GenericImports System.Reflection'************************************************************'类名称:ModelHelper  '命名空间:DAL'功能:实现datatable 对实体的转换功能'创建时间:2014-10-21'作者:周洲'小组:**'**************************************************************Public Class ModelHelper    ''' <summary>    ''' 将dataTable中的数据转换为实体集合    ''' </summary>    ''' <typeparam name="T"></typeparam>    ''' <param name="dt"></param>    ''' <param name="ts"></param>    ''' <returns></returns>    ''' <remarks></remarks>    Public Shared Function ConvertToList(Of T As New)(dt As DataTable, ts As IList(Of T))        '获得T的类型          Dim type As Type = GetType(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                            'If value IsNot Nothing 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 FunctionEnd Class

    D层中定义一个List<>,定义一个dt变量接收传回来的数据,调用上面写的函数,填入mylist和dt就转换成功啦。



''' <summary>    ''' 用有参数的查询方法查询充值表,条件是卡号    ''' </summary>    ''' <param name="student"></param>    ''' <returns></returns>    ''' <remarks></remarks>    Public Function QueryReRecord(student As ModelReInfo) As List(Of ModelReInfo) Implements IDAL.IRecharge.QueryReRecord        Dim str As String = "Select cNO,rAdd,rDate,rTime,rUID from T_Recharge where cNo=@cNo"        Dim helper As New SqlHelper        Dim para As SqlParameter() = {            New SqlParameter("@cNo", student.cNo)            }        If student.cNo Is Nothing Then            Throw New Exception("请填写卡号")        End If        Dim dt As New DataTable        Dim myList As New List(Of ModelReInfo)        dt = helper.ExecSelect(str, CommandType.Text, para)        If (dt.Rows.Count > 0) Then            myList = ModelHelper.ConvertToList(dt, myList)            Return myList        Else            Throw New Exception("没有记录!")            Return Nothing        End If    End Function




四、总结

    上面讨论了这么多,那到底为什么不能使用DataTable呢?归根结底,我认为做系统最主要是体现软件发展的分层处理,体现三层之间的分工合作(既然DataTable这么的破坏结构又实用,那我们照常用它,但是转换它),提高开发效率和降低耦合度,以使人能处理更加复杂的问题,更高层的抽象。不断的抽象,这就是目的吧。




1 0
原创粉丝点击