泛型会合代替DataTable
在机房重构过程中,在实现将数据库中数据显示到DataGridView控件这一功能时,遇到这样一个问题:由于在SqlHelper类中,定义查询操作时是将数据库,得到的是DataTable和DataSet对象(表),因此在使用DataGridView、Textbox等控件对数据进行绑定时,需要读取数据库中的字段。
举一例子,在实现“查询卡中金额”这一功能,需要将数据中Card_info表中的数据显示到文本框中。由于在D层中实现与数据库交互,获得的是DataTable对象(也就是Card_info表)。因此,在U层中的文本框需要与Card_info表中的字段一一对应起来。代码如下:
If card.Rows.Count Then txtClass.Text = card.Rows(0)(5).ToString() txtName.Text = card.Rows(0)(3).ToString() txtDepartment.Text = card.Rows(0)(8).ToString() txtGrass.Text = card.Rows(0)(4).ToString() txtSex.Text = card.Rows(0)(2).ToString() txtState.Text = card.Rows(0)(7).ToString() txtCash.Text = card.Rows(0)(6).ToString() txtStuNo.Text = card.Rows(0)(1).ToString() End If这样做功能虽然能实现,但是却在一些缺陷:
1、必须了解数据库的结构,降低数据库的安全性。
2、在代码编写过程容易写错,而且编译器不检查。
3、在程序中进行数据传递的是DataTable,不再是实体,违背了面向对象编程的思想。
4、DataTable为弱类型,无法直观的看出字段的数据类型。
DataTable对象是我们在程序与数据库交互必须使用的,为了弥补DataTable对象给我们在重构机房中带来的不便,这时我们采用将Datatable转化成泛型集合来解决这个问题。核心思想图:
实体类即数据库的映射,因此实体类中的属性和数据库表中的字段是相对应的。把DataTable中的每一行记录视为一个实体类,把其中的字段读取出来,存放到实体类的属性中,再把所有的实体类存在泛型集合中。因此,DataTable中有多少个记录,泛型集合中就有多少个实体类,每个实体类的属性和DataTable的字段是相对应的。这样做的好处是:
1、编写B层的人员无需手动填写需要的字段,直接按一下点,全都提示出来了,想用哪个用哪个,不会出现写错的情况。
2、不必了解数据库结构,保证了数据库的安全性。
3、在程序中进行数据传递的是实体,符合面向对象思想。
4、实体类的属性是强类型,每个字段的类型都是已知的。
好了,了解了泛型的好处和特点,现在看看是如何实现DataTable转换成泛型的。代码如下:
Imports System.Collections.Generic Imports System.Reflection '************************************************************ '类名称:EntityHelper '命名空间:Entity '功能:实现datatable类型对实体的转换功能 '创建时间:2015-2-14 '作者:孟浩杰 '小组:** '************************************************************** Public Class EntityHelper ''' <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 '设置对象的属性值。 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
总结
- 4楼u011500356昨天 21:16
- 以后咱会接触到数据持久化的问题的!这个更有意思
- 3楼u013034223昨天 17:19
- 使用datatable确实没有泛型方便
- 2楼u013036959昨天 11:06
- 技术方面不多说,继续努力啊!
- 1楼u011500356昨天 21:26
- 以后咱会接触到数据持久化的问题的!这个更有意思