机房重构——泛型 or DataTable?

来源:互联网 发布:p2p网络投资理财 编辑:程序博客网 时间:2024/04/30 22:38

        机房进行到了一大半的时候,发现很多师哥师姐在把数据库中的查询结果返回到B层的时候是使用的泛型,这也是我第一次接触到泛型,因为之前传回参数都是使用的DataTable,那么两者有什么区别呢?今天就来聊聊这个事儿


什么是DataTable?


它是一个临时保存数据的网格虚拟表(表示内存中数据的一个表),使用它的对象包括DataSet和DataView。下边是SqlHelper类中的一段代码,DataSet是由一组DataTable组成的,DataSet通过SqlDataAdapter,使用数据源中的数据生成和填充到每一个DataTable中可以将DataSet理解为数据库中表的集合,而datatable就是那些个虚拟的表

<span style="font-size:14px;">    Public Function ExecDataTable(ByVal cmdText As String, ByVal cmdType As CommandType, ByVal paras As SqlParameter()) As DataTable        Dim sqlAdapter As SqlDataAdapter        Dim dt As New DataTable        Dim ds As New DataSet        cmd.CommandText = cmdText        cmd.CommandType = cmdType        cmd.Connection = conn        cmd.Parameters.AddRange(paras) '参数添加        sqlAdapter = New SqlDataAdapter(cmd) '实例化adapter适配器        Try            sqlAdapter.Fill(ds)             dt = ds.Tables(0) '将数据填充到虚拟表格中            cmd.Parameters.Clear()        Catch ex As Exception            MsgBox(ex.Message)        Finally            Call CloseCmd(cmd)        End Try        Return dt    End Function</span>


什么是泛型?


1.在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,不能代表个别对象。(这是当今较常见的定义)

2.在程序编码中一些包含参数的类。其参数可以代表类或对象等等。(人们大多把这称作模板)不论使用哪个定义,泛型的参数在真正使用泛型时都必须作出指明。


两者的区别?


1.两者如何让将数据赋值给实体


DataTable


<span style="font-size:14px;">    Public Function inquireBalance(ByVal cardInfo As Entity.CardEntity) As Entity.StudentEntity        Dim fa As New Factory.Factory        Dim istudent As IDAL.IStudentDAL        Dim dt As DataTable        Dim studentInfo As New Entity.StudentEntity  '实例化学生信息的实体        istudent = fa.CreateStudentInfo        dt = istudent.InquireBalance(cardInfo)        If dt.Rows.Count = 1 Then            Dim drows As DataRow            drows = dt.Rows(0)            studentInfo.Sno = drows("sNo").ToString.Trim()   '将表格中的数据赋实体,字段相对应            studentInfo.Age = drows("age").ToString.Trim()            studentInfo.Sname = drows("sname").ToString.Trim()            studentInfo.Sex = drows("sex").ToString.Trim()            studentInfo.ClassS = drows("class").ToString.Trim()            studentInfo.Balance = drows("balance").ToString.Trim()            studentInfo.Department = drows("department").ToString.Trim()            studentInfo.Explain = drows("explain").ToString.Trim()            studentInfo.Major = drows("major").ToString.Trim()            studentInfo.Grade = drows("grade").ToString.Trim()            'studentInfo.Status = drows("cardStatus").ToString.Trim()        Else            MsgBox("没有该卡号或者卡号已经注销")        End If        Return studentInfo    End Function</span>


泛型

<span style="font-size:14px;">Function checkLineRecord(ByVal cardInfo As Entity.CardEntity) As List(Of Entity.LineRecordEntity) '根据输入卡号查询上机记录表        iline = fa.CreateLineRecord        Dim linelist As List(Of Entity.LineRecordEntity)        linelist = iline.inquireLineRecord(cardInfo)        If IsNothing(linelist) = False Then            Return linelist        Else            'MsgBox("该卡号没有上机记录!")            Return Nothing        End If    End Function</span>


从上边可以清楚的看出,datatable需要一个字段一个字段的还要对应好实体的字段去赋值,显而易见,这样做非常的麻烦,首先你要知道数据库中的字段有哪些,其次如果数据库中的数据字段更改了,那么B层这个类就需要重新被打开更改,这样B层和数据库的耦合性就非常的高了,如果开发是分层进行的,那么B层的开发人员还要知道数据库有哪些表哪些字段才能做到精准的给实体赋值,这就违背了我们软件开发的基本原则。

再来看看泛型,在D层我们得到数据库传来的DataTable,然后将其转化成泛型集合,这时,实体就已经带上参数了,在B层我们就可以看到泛型中有哪些实体类,所以B层的开发人员就不需要知道数据库中有哪些字段,因为传过来的就是数据库中这些元素的集合。


2.性能方面

在网上找了很多资料,都说泛型能够提高系统性能,看到这么一段话:

在计算机中经常用到一些数据结构,如队列,链表等,而其中的元素以前一般这么定义:object a=new object();这样就带来一个严重的问题,用object来表示元素没有逻辑问题,但每次拆箱、封箱就占用了大量的计算机资源,导致程序性能低下,而这部分内容恰恰一般都是程序的核心部分,如果使用object,那么程序的表现就比较糟糕。而使用泛型则很好的解决这个问题,本质就是在编译阶段就告诉编译器,数据结构中元素的种类,既然编译器知道了元素的种类,自然就避免了拆箱、封箱的操作,从而显著提高程序的性能。比如List<string>就直接使用string对象作为List的元素,而避免使用object对象带来的封箱、拆箱操作,从而提高程序性能。

       因为拆箱和装箱第一遍学的时候没有总结,所以上边这段话听得云里雾里,下一篇就总结一下拆箱和装箱的问题~


学生上机记录查询例子:


U层

<span style="font-size:14px;"> Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click        '判断文本框是否为空        If txtCardNO.Text = "" Then            MsgBox("请输入卡号")            txtCardNO.Focus()            Exit Sub        End If        Try            Dim linebll As New BLL.LineRecordBLL            Dim cardinfo As New Entity.CardEntity            cardinfo.CardNO = txtCardNO.Text            Dim strResult As Boolean            strResult = linebll.inquireCardNo(cardinfo)            If strResult = True Then  '如果有这个卡号                Dim linelist As List(Of Entity.LineRecordEntity) '实例化泛型集合                linelist = linebll.checkLineRecord(cardinfo) '调用B层的查询方法                If IsNothing(linelist) = False Then                    gridLineRecord.DataSource = linelist  '泛型集合与datagridview                Else                    MsgBox("该卡号没有上机记录!")                End If            Else                MsgBox("该卡号没有注册或已经停用!")            End If        Catch ex As Exception            MsgBox(ex.Message)        End Try</span>

B层:

    Function inquireCardNo(ByVal cardInfo As Entity.CardEntity) As Boolean  '所有学生都可以来查询,不限制注销的挂失的还是正在使用的        iline = fa.CreateLineRecord        Dim dt As DataTable        Dim flag As Boolean        dt = iline.ExistAllCard(cardInfo)        If dt.Rows.Count < 1 Then            flag = False        Else            flag = True        End If        Return flag    End Function    Function checkLineRecord(ByVal cardInfo As Entity.CardEntity) As List(Of Entity.LineRecordEntity) '根据输入卡号查询上机记录表        iline = fa.CreateLineRecord        Dim linelist As List(Of Entity.LineRecordEntity)        linelist = iline.inquireLineRecord(cardInfo)        If IsNothing(linelist) = False Then            Return linelist        Else            'MsgBox("该卡号没有上机记录!")            Return Nothing        End If    End Function

datatable转泛型的方法

<span style="font-size:14px;">Imports System.ReflectionImports System.Collections.GenericPublic Class DataToList    Public Shared Function convertToList(Of T As {New})(ByVal dt As DataTable) As IList(Of T) '将datatable转化为泛型集合        '注意:1.convertToList(of T as {New})这里的new是用来约束t的,必须有,不然new T的时候会出现错误        '2.new约束在c#和vb.net里边的写法是不一样的,c#里面用的是where来为t加约束的        Dim myList As New List(Of T) '定义最终返回的集合        Dim myType As Type = GetType(T) '得到实体类的类型名        Dim dr As DataRow '定义行集        Dim tempName 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            '遍历该对象的所有属性            For Each pr In propertys                tempName = pr.Name '将属性名称赋值给临时变量                '检查DataTable是否包含此列(列名==对象的属性名)                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(myT, value, Nothing)                    End If                End If            Next            myList.Add(myT) '添加到集合        Next        Return myList    End FunctionEnd Class</span>


D层:

Public Class LineRecordDAL : Implements IDAL.ILineRecordDAL    Dim sqlhelper As New SQLHelper.sqlHelper    Dim cmdType As CommandType = New CommandType()    Public Function ExistAllCard(cardInfo As Entity.CardEntity) As DataTable Implements IDAL.ILineRecordDAL.ExistAllCard        Dim paras As SqlParameter() = {New SqlParameter("@cardno", cardInfo.CardNO)}        Dim cmdText As String        cmdText = "select * from Card_Info where cardNo=@cardno"  '不管是使用还是不在使用的卡都可以查上机记录        Dim dt As DataTable        dt = sqlhelper.ExecDataTable(cmdText, CommandType.Text, paras)        Return dt    End Function    Public Function inquireLineRecord(cardInfo As Entity.CardEntity) As List(Of Entity.LineRecordEntity) Implements IDAL.ILineRecordDAL.inquireLineRecord        Dim cmdText As String        Dim paras As SqlParameter() = {New SqlParameter("@cardno", cardInfo.CardNO)}        cmdText = "select * from LineRecordview  where cardNo=@cardno and consumeMoney<>''"  '搜索正在上机的卡号        Dim dt As DataTable        dt = sqlhelper.ExecDataTable(cmdText, CommandType.Text, paras)        Dim myList As List(Of Entity.LineRecordEntity)        If dt.Rows.Count > 0 Then            '将dt转换为泛型集合            myList = DataToList.convertToList(Of Entity.LineRecordEntity)(dt)            Return myList        Else            Return Nothing        End If    End Function


总结:

其实重构机房就是了解一个有一个有效的工具,虽然我不会玩游戏,但是我觉得这些有利的工具就是我们升级打怪最重要的武器,我们在代码的世界中一路打打杀杀,得到一个有一个牛B的武器,我们的技能也随之修炼的更加炉火纯青,今目标的项目就是要去做的任务,我们需要做的就是不断提升自己的能力,不断探索未知的武器,打败一个又一个的困难,在任务的终点地方,插上我们代表胜利的可爱的小旗子,Fighting~~~









0 0
原创粉丝点击