一直不能理解我用着实体好好地,为什么非要换成DataTable,问别人的结果是:因为泛型特别好使。我就纳闷了,这又跟泛型有什么关系。问了好多都不是我要的结果,牛角尖上来了,那就自己搜索资料理解吧。
首先说:为什么要用实体?
对于大量的数据来说,还向VB版机房收费那样定义变量做参数显然是不合适的,一些简单的窗体还好,如登录窗体,就两个字段;要是换做注册窗体,起码得有十几个变量,很容易造成参数匹配上的错误,而且每次增删改查还要传递十几个参数,简直是麻烦透了。
为此,我们引入了实体。实体对应的不是数据库中的单个字段,而是整张表。通过抽象封装,将每个表中的字段作为一个类的属性封装在指定的一个实体中。这样传递数据的时候,我们只传递一个实体就可以啦,当你需要哪个字段的时候,通过get()set()就可以啦,这样明显比一大堆参数飘来飘去整齐的多,灵活性增强,安全性增强,便于维护和拓展。(当然,如果是一两个字段,那传参数和传实体是一样的啦)
再说:DataTable
一直以为实体是对变量型参数的升级,而DataTable是对实体的升级。其实大错特错。其实用过DataTable之后就会感觉出来,DataTable是一个虚拟表,这个表跟数据库的紧密相当密切,虚拟表中的每个字段分别对应每个数据库表中的字段。而DataTable跟实体有什么联系呢?从数据库中查到的数据其实是默认存放到DataTable虚拟表中的,我们知道了实体的好处,所以通过反射将DataTable中的字段封装成实体对象后返回。换句话来说,实体的来源就是DataTable进行属性的反射得到的。所以,从面向对象角度说,实体是DataTable的升级。DataTable是一个虚拟表,更致力于表中的字段,可以直接进行字段的运算啊什么的比较方便,字段操作的灵活性比较强,性能比较好。
最后说:为什么使用泛型?
泛型结合类可以将类型参数用做它所存储的对象的类型的占位符。类型参数作为其字段的类型和其方法的参数类型出现。这样说可能有些抽象,用图来表示吧。个人觉得这张图最好不过,就直接引用不做修改了。
可以说,泛型是在实体上进一步的封装,以实体为参数形成集合。这样一个泛型集合中,就可以最大容量的反应数据库,可以方便多张表的操作。
以简单的BasicData表的查询为例。首先写一个DataTable转换成泛型的类:ConvertHelper。代码如下:
Imports System.Collections.Generic '增加泛型的命名空间 Imports System.Reflection '引入反射 Public Class ConvertHelper '将datatable转化为泛型集合 Public Shared Function convertToList(Of Turn As {New})(ByVal dt As DataTable) As IList(Of Turn) 'convertToList(Of Turn As {New}) 这里的new是用来约束T的 Dim myList As New List(Of Turn) '定义最终返回的集合 Dim myTpye As Type = GetType(Turn) '得到实体类的类型名 Dim dr As DataRow '定义行集 Dim tempName As String = String.Empty '定义一个临时变量 '遍历DataTable的所有数据行 For Each dr In dt.Rows Dim myTurn As New Turn '定义一个实体类的对象 Dim propertys() As PropertyInfo = myTurn.GetType().GetProperties() '定义属性集合 Dim Pr As PropertyInfo '遍历该对象的所有属性 For Each Pr In propertys tempName = Pr.Name '将属性名称赋值给临时变量 If (dt.Columns.Contains(tempName)) Then '将此属性与datatable里的列名比较,查看datatable是否包含此属性 '判断此属性是否有Setter If (Pr.CanWrite = False) Then '判断此属性是否可写,如果不可写,跳出本次循环 Continue For End If Dim value As Object = dr(tempName) '定义一个对象型的变量来保存列的值 If (value.ToString <> DBNull.Value.ToString()) Then '如果非空,则赋给对象的属性 Pr.SetValue(myTurn, value, Nothing) '在运行期间,通过反射,动态的访问一个对象的属性 End If End If Next myList.Add(myTurn) '添加到集合 Next Return myList '返回实体集合 End Function End Class具体的D层调用如下:
''' <summary> ''' 查询BasicData并显示 ''' </summary> ''' <param name="basicdataentity"></param> ''' <returns></returns> ''' <remarks></remarks> Public Function SelectBasicData(ByVal basicdataentity As Entity.BasicDataEntity) As List(Of Entity.BasicDataEntity) Dim sql As New SQLHelper.SqlHelper Dim dt As DataTable Dim mylist As List(Of Entity.BasicDataEntity) Dim strsql As String = "Select * from BasicData " '定义SQL语句 dt = sql.ExecSelectNo(strsql, CommandType.Text) mylist = ConvertHelper.convertToList(Of Entity.BasicDataEntity)(dt) Return mylist End Function小结:
从DataTable到实体,再到泛型,一步一步更接近面向对象。但是具体怎么用,用什么,三个数据传递方式各有千秋。