刚刚开始机房重构的时候用的最多的就是DataTable,在用的时候感觉有一点点别扭,因为D层从数据库中
把数据取出来之后直接通过DataTable返回到B层和U层了,这样对于数据库数据的安全性不太好。然后慢慢知
道了泛型,通过泛型可以很好的解决数据安全的问题
一、DataTable
Public Function QueryCard(card As Entity.CardEntity) As Entity.CardEntity Implements ICard.QueryCard
Dim helper As New SqlHelper() '实例化SqlHelper的对象为helper
Dim dt As DataTable '接收从SqlHelper中返回的DataTable
Dim CardInfo As Entity.CardEntity = New Entity.CardEntity()
Dim Query As String = "select * from card_info where cardno=@cardno" '存储Sql字段<span style="white-space:pre">
</span><pre name="code" class="csharp"> '实例化SqlParameter,并传入参数
Dim sqlParams As SqlParameter() = {New SqlParameter("@cardno", card.CardNo)}
dt = helper.ExecSelect(Query, sqlParams) '调用对象helper的方法
'把DataTable中的数据分别放入实体CardInfo中对应的字段
Try
CardInfo.CardNo = dt.Rows(0)(0)
CardInfo.Dates = dt.Rows(0)(5)
CardInfo.Time = dt.Rows(0)(6)
CardInfo.Status = dt.Rows(0)(7)
CardInfo.IsCheck = dt.Rows(0)(8)
CardInfo.Explain = dt.Rows(0)(9)
CardInfo.CardType = dt.Rows(0)(1)
CardInfo.Cash = dt.Rows(0)(2)
CardInfo.StudentNo = dt.Rows(0)(3)
Catch ex As Exception
'出错以后的提示
MsgBox("卡号不存在或错误", CType(vbOKOnly + MsgBoxStyle.Exclamation, MsgBoxStyle), "提示")
End Try
Return CardInfo '返回实体
End Function
这是把DataTable中的数据在D层中直接赋值给实体了,个人认为这样做会相对好一点,因为从数据库
取得的数据不会直接返回给U层和B层;当然也可以在D层直接将获得的DataTable返回给U层B层,然后在U层
对DataTable中的数据进行操作,很明显这样对数据来说是很不安全的,而且三层之间通过DataTable传输
数据也会增加三层的耦合度
二、泛型
'DataTable转换为泛型
Public Shared Function ConvertList(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 '定义DataTable的行集
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 'PropertyInfo的实例化
'遍历pr对象在集合中的所有属性
For Each pr In Propertys
TmpName = pr.Name '属性名称赋值给定义的临时变量
'检查DataTable中是否包含此属性,如果包含继续执行
If (dt.Columns.Contains(TmpName)) Then
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) '把获得的属性添加到集合中
Next
Return MyList '返回集合
End Function
D层直接调用该方法即可
Public Function SelectStudent(ByVal student As Entity.StudentEntity) As IList(Of Entity.StudentEntity) Implements ISelectStudent.SelectStudent
Dim helper As New SqlHelper
Dim dt As DataTable
Dim sql As String = "select * from student_info where studentno=@studentno"
Dim stuInfo As List(Of Entity.StudentEntity)
<span style="white-space:pre"> </span>
Dim para As SqlParameter() = {New SqlParameter("@studentno", student.StudentNo)}
<span style="white-space:pre"> </span>'调用SqlHelper方法
dt = helper.ExecSelect(sql, para)
<span style="white-space:pre"> </span>'DataTable类型转换为泛型
stuInfo = Entity.Genericity.ConvertList(Of Entity.StudentEntity)(dt)
Return stuInfo
End Function
这样通过泛型的转换可以让B层和D层之间解耦,泛型定义的类型限制也可以在很大程度上保证数据的安
全性。
三、小结
在使用泛型的时候一定要注意数据类型,实体中的数据类型与数据库的数据类型一定要保持一直
在多用一些自己没用的技术,对自己很有帮助的。。