做系统前期,抱着“实现了三层已经很不错了”的心情,并没有考虑到DataTable传到B层,或传到U层与DataGridView绑定,显示数据有什么错误的地方。后来“偷”听了一节课,才知道返回DataTable是破坏三层结构的。于是就开始了三层架构中DataTable变形记的探索。
变形之前我考虑到了以下几点内容,也是看了很多的资料,总结下来的。(本身是菜鸟一枚,So...下面展示的代码不是我自己写的,参考了十期师哥的博客。站在巨人肩膀上啦)
DataTable是数据集的填充,List<>是对象化的填充。DataTable是弱类型,没有办法直接看出数据表中字段的数据类型,List<>是强类型。最大的区别是,List<>可以灵活转换,不用装箱和拆箱(装箱拆箱:利用装箱和拆箱功能,可通过允许值类型的任何值与Object 类型的值相互转换),这个过程中可能会造成数据的错误丢失,这样看来DataTabel也不是很安全的。
图一(三层依赖model传数据)
图二(三层依赖DataTable传数据)
从上面的图中明显看得到,DataTable的出现,使UI,BLL,DAL层都去直接的访问它了,而我们自己写的Model被甩到了一边。这一点就可以看出DataTable破坏了我们的三层结构。那么如果不使用DataTable,问题就来了。一条数据好处理,就实例化一个实体对象就可以了。如果是多个数据呢?那么就引出了我们需要使用的泛型集合了,简单的可以理解为一群实体。
回答这个问题,其实就是在回答泛型集合有什么好处?因为它的优点,我们才考虑去使用它。
优点:
缺点:
这里我们需要写一个转换的类,让DataTable实现变身:
Imports System.Collections.Generic Imports 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 Function End Class
''' <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这么的破坏结构又实用,那我们照常用它,但是转换它),提高开发效率和降低耦合度,以使人能处理更加复杂的问题,更高层的抽象。不断的抽象,这就是目的吧。