机房重构前期一直是用的DataTable来返回数据库中的值,当时没有感觉很麻烦,后来接触了泛型,才发现DataTable还是比较麻烦的。
DataTable:
不允许透明检索数据,应用程序和数据库是强耦合,对数据库结构的任何改变你都需要你的程序有所改动,这样就造成了代码和数据库耦合性更强。在你写U层代码的时候需要知道数据库字段的顺序。例如
Dim table As DataTable
table = facade.CheckData()
'使用泛型,就必须知道数据库的结构
txtRate.Text = table.Rows(0).Item(0)
txtTmpRate.Text = table.Rows(0).Item(1)
txtUnitTime.Text = table.Rows(0).Item(2)
txtLeastTime.Text = table.Rows(0).Item(3)
txtPrepareTime.Text = table.Rows(0).Item(4)
txtLimitCash.Text = table.Rows(0).Item(5)
泛型的作用是避免强制类型转换,提高类型安全,提高代码的重用性,减少装箱 拆箱提高性能,减少错误。
DataTable转泛型:
DataTable偏向于面向过程,使用时需要知道数据库中它的位置;List偏向于面向对象,只需要点出它的字段名即可,不需要知道数据库里面的结构。
下面用一张图来表示一下:
实体类是数据库的映射,实体类的属性和数据库表中的字段相对应。
把DataTable中每一行记录作为一个实体类,把其中的字段读取出来存放在实体类的属性中,再把所用实体类存放在泛型集合中。
优点:
•无需知道数据库的结构
•符合面象对象的思想
注意事项:
•实体类的属性必须和数据库表中字段名一模一样
实例:
就拿基本数据设定来说吧
1.建立转换泛型的模块/类
我是建立在了D层
Imports System.Reflection
Public Class ConvertHelper
'将datatable转化为泛型集合
Public Shared Function ConvertToList(Of Turn As {New})(ByVal dt As DataTable) As IList(Of Turn)
'这里new是用来约束T的
Dim myList As New List(Of Turn) '定义最终返回的集合
Dim myType As Type = GetType(Turn) '得到实体类的类型名
Dim dr As DataRow '定义行集
Dim tempName As String = String.Empty '定义一个临时变量
'遍历该对象的所有 数据行
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 '跳出,继续执行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
2.使用泛型
Imports System.Data.SqlClient
Public Class DataDAL : Implements IDAL.IBasicData
Public Function CheckData() As List(Of Entity.BasicDataInfo) Implements IDAL.IBasicData.CheckData
Dim sqlHelper As New SqlHelper.SqlHelper
Dim sql As String
Dim table As New DataTable
Dim mylist As New List(Of Entity.BasicDataInfo)
sql = "Select * from BasicData_Info "
table = sqlHelper.ExecSelectNo(sql, CommandType.Text)
mylist = ConvertHelper.ConvertToList(Of Entity.BasicDataInfo)(table)
Return mylist
End Function
End Class
3.泛型数据的获取
Dim mylist As New List(Of Entity.BasicDataInfo)
mylist = facade.CheckData()
txtRate.Text = mylist(0).Rate
txtTmpRate.Text = mylist(0).tmpRate
txtUnitTime.Text = mylist(0).unitTime
txtLeastTime.Text = mylist(0).leastTime
txtPrepareTime.Text = mylist(0).prepareTime
txtLimitCash.Text = mylist(0).limitCash
直接就可以点出它的字段,不需知道数据库结构
问题:
类型“System.String”的对象无法转换为类型“System.Char”
以为数据库里设置的是Char类型,里面没有string类型,在实体层里面设置的也是Char类型,将其改为string类型即可
总结:
实践是检验真理的唯一标准,这次真正实践过,才知道泛型比DataTable好用很多。