【机房重构】一步一步往上爬——七层中的那些事

	机房重构开始已经一个多星期了,从最开始的理解登录到现在已经成功完成至少一次的“增”、“删”、“改”、“查”的操作,现在在七层的这个大环境下,从最开始的奄奄一息,终于变得生龙活虎起来了。
	之前总是听师哥师姐们说,敲完登录一条线了,后面就会很顺利了。可是,从我来说,事实并非如此。然而,磕磕绊绊,四个字足以形容我的这些天。不过,我心态好,我可以忍受一个人花时间调代码的孤独,再说,我也可以找小伙伴、找师父帮助我,我有什么理由不成功。
	我们在第一次机房收费系统的时候,就有很深的体会:完成了一次增删改查的操作,后面的路就平坦许多。而在机房重构中,这样的体会依旧出现了,只不过我出现的时间晚些,别人在敲完登录之后就有体会了,而我是在自己一次次摸索之后,完成了一些其他的功能,才有所体会的。
	下面就开始进入正题,和大家一起来看看,在七层中的那些事。
	首先说说,“增”、“删”、“改”、“查”。这四个对数据库的操作,思路都是一样的。总结来说,就是以下四条:
	1.增、删、改(有参数的)——把数据从U层传入D层,数据库做相应修改,返回给U层一个修改提示,即成功与否;
	2.增、删、该(无参数的)——根据U层操作,对数据库做相应修改,返回给U层一个修改提示,即成功与否;
	3.查(无参数的)——把数据从D层传入U层,直接返回数据库中的表信息;
	4.查(有参数的)——把数据从U层传入D层,找到相应的数据,返回一个符合查询的虚拟表;
	做完这些,自己才体会到在上篇博客中提到的SqlHelper的好处。之前,他们都说这个好,而自己却不能理解,很想弄清楚,深入研究,还是失败告终。这一次,自己没有刻意花时间去琢磨,而是在敲代码的过程中,用着用着就明白了。下面,便是我用到的SQLHelper封装好的代码:
Public Class SqlHelper
    '定义变量
    '获得数据库的连接字符串
    Private ReadOnly strConnection As String = ConfigurationManager.AppSettings("ConnStr")
    '设置连接
    Dim conn As SqlConnection = New SqlConnection(strConnection)
    '定义cmd命令
    Dim cmd As New SqlCommand

    ''' <summary>
    ''' 执行增删改三个操作,(有参)返回值为Boolean类型,确认是否执行成功
    ''' </summary>
    ''' <param name="cmdText">需要执行语句,一般是Sql语句,也有存储过程</param>
    ''' <param name="cmdType">判断Sql语句的类型,一般都不是存储过程</param>
    ''' <param name="paras">参数数组,无法确认有多少参数</param>
    ''' <returns></returns>
    ''' <remarks>2015-2-3 10:05:46</remarks>
    Public Function ExecAddDelUpdate(ByVal cmdText As String, ByVal cmdType As CommandType, ByVal paras As SqlParameter()) As Boolean
        '将传入的值,分别为cmd的属性赋值
        cmd.Parameters.AddRange(paras)   '将参数传入
        cmd.CommandType = cmdType            '设置一个值,解释cmdText
        cmd.Connection = conn                '设置连接,全局变量
        cmd.CommandText = cmdText            '设置查询的语句    

        Try
            conn.Open()                      '打开连接
            Return cmd.ExecuteNonQuery()     '执行增删改操作
            cmd.Parameters.Clear()           '清除参数
        Catch ex As Exception
            Return False                         '如果出错,返回0
        Finally
            Call CloseConn(conn)
            Call CloseCmd(cmd)
        End Try
    End Function
    ''' <summary>
    ''' 执行增删改三个操作,(无参)
    ''' </summary>
    ''' <param name="cmdText">需要执行语句,一般是Sql语句,也有存储过程</param>
    ''' <param name="cmdType">判断Sql语句的类型,一般都不是存储过程</param>
    ''' <returns>Interger,受影响的行数</returns>
    ''' <remarks>2015-2-3 10:05:39</remarks>
    Public Function ExecAddDelUpdateNo(ByVal cmdText As String, ByVal cmdType As CommandType) As Boolean
        '为要执行的命令cmd赋值
        cmd.CommandText = cmdText       '先是查询的sql语句
        cmd.CommandType = cmdType       '设置Sql语句如何解释
        cmd.Connection = conn           '设置连接    

        '执行操作
        Try
            conn.Open()
            Return cmd.ExecuteNonQuery()
        Catch ex As Exception
            Return False
        Finally
            Call CloseConn(conn)
            Call CloseCmd(cmd)
        End Try
    End Function

    ''' <summary>
    ''' 执行查询的操作,(有参),参数不限
    ''' </summary>
    ''' <param name="cmdText">需要执行语句,一般是Sql语句,也有存储过程</param>
    ''' <param name="cmdType">判断Sql语句的类型,一般都不是存储过程</param>
    ''' <param name="paras">传入的参数</param>
    ''' <returns></returns>
    ''' <remarks>2015-2-3 10:05:32</remarks>
    Public Function ExecSelect(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赋值
        cmd.CommandText = cmdText
        cmd.CommandType = cmdType
        cmd.Connection = conn
        cmd.Parameters.AddRange(paras)  '参数添加
        sqlAdapter = New SqlDataAdapter(cmd)  '实例化adapter
        Try
            sqlAdapter.Fill(ds)           '用adapter将dataSet填充
            dt = ds.Tables(0)             'datatable为dataSet的第一个表
            cmd.Parameters.Clear()        '清除参数
        Catch ex As Exception
            MsgBox("查询失败", CType(vbOKOnly + MsgBoxStyle.Exclamation, MsgBoxStyle), "警告")
        Finally                            '最后一定要销毁cmd
            Call CloseCmd(cmd)
        End Try
        Return dt
    End Function

    ''' <summary>
    ''' 执行查询的操作,(无参)
    ''' </summary>
    ''' <param name="cmdText">需要执行语句,一般是Sql语句,也有存储过程</param>
    ''' <param name="cmdType">判断Sql语句的类型,一般都不是存储过程</param>
    ''' <returns>dataTable,查询到的表格</returns>
    ''' <remarks>2015-2-3 10:05:23</remarks>
    Public Function ExecSelectNo(ByVal cmdText As String, ByVal cmdType As CommandType) As DataTable
        Dim sqlAdapter As SqlDataAdapter
        Dim ds As New DataSet
        '还是给cmd赋值
        cmd.CommandText = cmdText
        cmd.CommandType = cmdType
        cmd.Connection = conn
        sqlAdapter = New SqlDataAdapter(cmd)  '实例化adapter
        Try
            sqlAdapter.Fill(ds)           '用adapter将dataSet填充
            Return ds.Tables(0)             'datatable为dataSet的第一个表
        Catch ex As Exception
            Return Nothing
        Finally                            '最后一定要销毁cmd
            Call CloseCmd(cmd)
        End Try
    End Function

    ''' <summary>
    ''' 关闭连接
    ''' </summary>
    ''' <param name="conn">需要关闭的连接</param>
    ''' <remarks>2015-2-3 10:05:56</remarks>
    Public Sub CloseConn(ByVal conn As SqlConnection)
        If (conn.State <> ConnectionState.Closed) Then  '如果没有关闭
            conn.Close()                    '关闭连接
            conn = Nothing                  '不指向原对象
        End If

    End Sub
    ''' <summary>
    ''' 关闭命令
    ''' </summary>
    ''' <param name="cmd">需要关闭的命令</param>
    ''' <remarks>2015-2-3 10:06:03</remarks>
    Public Sub CloseCmd(ByVal cmd As SqlCommand)

        If Not IsNothing(cmd) Then          '如果cmd命令存在
            cmd.Dispose()                   '销毁
            cmd = Nothing
        End If
    End Sub
End Class
	敲的代码多了,对七层中的东西也是越来越熟悉了。下面,就从注册这一功能,重新感受一番七层给我的体会。
	注册首先明确涉及到一个新的表,所以,第一步就是添加配置文件,
<add key="StrCard"  value="CardDAL"/>
	第二封装实体,将注册表(也就是卡表)的各个字段都写入实体中,以便之后的各层之间的传参数。
Public Class EntityCard
    Private CardNo As String
    Private StudentNo As String
    Private RegisterDate As String
    Private RegisterTime As String
    Private Balance As String
    Private UserID As String
    Private IsCheck As String
    Private Type As String
    Private CardStatus As String

    Public Property Card() As String
        Get
            Return CardNo
        End Get
        Set(value As String)
            CardNo = value
        End Set
    End Property

    Public Property Student() As String
        Get
            Return StudentNo
        End Get
        Set(value As String)
            StudentNo = value
        End Set
    End Property

    Public Property RDate() As String
        Get
            Return RegisterDate
        End Get
        Set(value As String)
            RegisterDate = value
        End Set
    End Property

    Public Property RTime() As String
        Get
            Return RegisterTime
        End Get
        Set(value As String)
            RegisterTime = value
        End Set
    End Property

    Public Property BL() As String
        Get
            Return Balance
        End Get
        Set(value As String)
            Balance = value
        End Set
    End Property

    Public Property ID() As String
        Get
            Return UserID
        End Get
        Set(value As String)
            UserID = value
        End Set
    End Property

    Public Property Check() As String
        Get
            Return IsCheck
        End Get
        Set(value As String)
            IsCheck = value
        End Set
    End Property

    Public Property CardType() As String
        Get
            Return Type
        End Get
        Set(value As String)
            Type = value
        End Set
    End Property

    Public Property Status() As String
        Get
            Return CardStatus
        End Get
        Set(value As String)
            CardStatus = value
        End Set
    End Property

End Class
	第三创建接口方法,可根据需要自行创建,比如:添加学生,注册卡号等等。
Public Interface Card
    ''' <summary>
    ''' 创建注册的方法
    ''' </summary>
    ''' <param name="card"></param>
    ''' <returns></returns>
    ''' <remarks>2015-2-5 10:43:54</remarks>
    Function RegisterCard(ByVal card As Model.EntityCard) As Boolean
    ''' <summary>
    ''' 查询余额的方法
    ''' </summary>
    ''' <param name="card"></param>
    ''' <returns></returns>
    ''' <remarks>2015-2-5 23:05:15</remarks>
    Function QueryBalance(ByVal card As Model.EntityCard) As DataTable

End Interface
	第四创建抽象工厂+反射,经慕夏师父的一次详细指导后,对这一层的了解也是更深刻了些。它的好处就是可以避免出现大量的case或其他选择语句,因为工厂+反射自己会去查找相对应的数据表。如,下面指向的就是注册表:
 ''' <summary>
    ''' 实例化一个DAL中的Card表的类
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks>2015-2-5 10:17:38</remarks>
    Public Function CreateCard() As IDAL.Card
        Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & StrCard), IDAL.Card)
    End Function
	第五D层实现接口的方法。这里就会用到之前封装好的Sqlhelper类,根据实际情况,选择对应的某种操作。如注册卡号(属于有参数的增操作):
 ''' <summary>
    ''' 注册新卡
    ''' </summary>
    ''' <param name="card"></param>
    ''' <returns>返回一个Boolean型的值</returns>
    ''' <remarks>2015-2-5 12:25:04</remarks>
    Public Function AddCard(ByVal card As Model.EntityCard) As Boolean Implements Card.RegisterCard
        Dim Sql As String
        Dim table As Boolean
        Dim sqlParams As SqlParameter() = {New SqlParameter("@CNO", card.Card),
                                           New SqlParameter("@SNO", card.Student),
                                           New SqlParameter("@Date", card.RDate),
                                           New SqlParameter("@Time", card.RTime),
                                           New SqlParameter("@Balance", card.BL),
                                           New SqlParameter("@ID", card.ID),
                                           New SqlParameter("@Check", card.Check),
                                           New SqlParameter("@Type", card.CardType),
                                           New SqlParameter("@Status", card.Status)}
        Sql = "Insert into Card_Info Values(@CNO,@SNO,@Date,@Time,@Balance,@ID,@Check,@Type,@Status)"
        table = sqlhelper.ExecAddDelUpdate(Sql, CommandType.Text, sqlParams)
        Return table
    End Function
	这里实现的就是增加,在这一层,不一样的也就仅仅是有无参数或不同情况下的SQL语句写法不同。值得注意的是SQL语句的写法,往往会因为写法不正确而报错。“=”前后分别是数据库中的字段和封装好的实体的名称,两个不能有任何不同。
	第六B层方法封装,实现抽象工厂和接口的方法。
 ''' <summary>
    ''' 注册卡号
    ''' </summary>
    ''' <param name="card"></param>
    ''' <returns></returns>
    ''' <remarks>2015-2-5 21:19:31</remarks>
    Public Function AddCard(ByVal card As Model.EntityCard) As Boolean
        Dim factory As New Factory.ChargeSystemFactory()
        Dim Acard As IDAL.Card
        Dim flag As Boolean
        Acard = factory.CreateCard
        flag = Acard.RegisterCard(card)
        If flag = True Then
            MsgBox("注册卡号成功", , "提示")
        Else
            MsgBox("未成功注册", , "提示")
        End If
        Return flag
    End Function
	第七完成外观层对应方法的封装,以便调用B层方法将U层数据传入B层或返回数据给U层。
 ''' <summary>
    ''' 注册卡号
    ''' </summary>
    ''' <param name="card"></param>
    ''' <returns></returns>
    ''' <remarks>2015-2-6 10:04:41</remarks>
    Public Function AddCard(ByVal card As Model.EntityCard) As Boolean
        Dim add As New BLL.CardBLL()
        Dim flag As Boolean
        flag = add.AddCard(card)
        Return flag
    End Function
	第八U层传值。视情况,将需要传入的参数赋值给实体,从而通过调用外观层的方法,进行传参。
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
        Dim CardFacade As New Facade.CardFacade
        Dim card As New Model.EntityCard
        '调用卡
        card.ID = frmLogin.txtUserName.Text
        card.BL = txtMoney.Text
        card.Student = txtStudentNo.Text
        card.Card = txtCardNo.Text
        card.CardType = comboType.Text
        card.RDate = DateTime.Now.ToLongDateString()
        card.RTime = DateTime.Now.ToLongTimeString()
        card.Status = txtStatus.Text
        card.Check = "未结账"
        Dim flag1 As Boolean
        flag1 = CardFacade.AddCard(card)
    End Sub
	上面八条就是这些天自己敲完后总结出来的一个思路吧。每次一个新功能的开始,亦或是功能的调错,自己都是按着以上八步一步一步进行的,脑海中有个清晰的思路,才得以保证自己后面的路可以走下去,或者不会因为前方一片迷茫而不敢前行。
学习心得:
	机房重构进行的这些天,真是涨了不少知识。不论是遇到的错误还是一个功能的实现,都有一种收获的感觉。现在觉得七层中的这些东西也都是大同小异的了,所以说重复就是力量。刚开始的感觉一定是最不好的,但也是必须要经过的,这就是一个过程。接下来,依旧一步一步往上爬,机房重构,继续奋战~~
时间: 2024-10-03 21:50:40

【机房重构】一步一步往上爬——七层中的那些事的相关文章

【机房重构】一步一步往上爬——不仅仅是三层

不知道大家还记不记得之前学习的UML中一个单独列出来的一种图,也就是这次我想说的包图.那个时候,让我们画机房收费系统的各种图,用例图.类图等等,通过自己反复琢磨,还都勉勉强强画出来了.唯独只有包图,我是一点东西也没有画上,只是见到了传说中的"包"是长什么样子的. 现在到了机房重构的阶段了,之前也学习了三层,终于是知道了包图该怎么画了.但也不仅仅是理解了包图,而且也是见证到了包图是如何在一步一步层层升级的.下面就将用一个机房系统中的登录实例来看看为什么说<不仅仅是三层>. 三

【机房重构】一步一步往上爬——又见UML与文档

机房重构的代码编写完成后,下一阶段的任务就是画图和文档了.在师父细心的一番指导后,开始动工了. 在数据库设计的时候,自己也有根据自考学习的知识,画了张ER图.到现在系统完成后,回头看之前贴在博客上的那张ER图,也是错漏百出,自己都不知道误导了多少人了.. 今天一开始把ER图给师父看,师父第一个问题就是问ER图是给谁看的?我顿时懵了.师父接着说ER图是给用户看的,你用英文写,用户看的懂吗? 下面就从ER图说起: ER图,是需要在需求分析文档中出现的,那么就是需要给用户看到的,而不是程序员或者说是开

【机房重构】一步一步往上爬——验收给了我什么

整个机房重构过程中,一共经历了两次验收.一次是关于系统编程:一次是关于画图与文档,每一次,师父都是耐心.细心地指导.要问验收给了我什么,看下面的博客内容便清楚了. 个人机房重构可分为两个阶段,前期主要是代码的编写,后期主要是画图. 在前期阶段,慕夏师父也是非常关心我的进展,时常来我这里看看,问问我有什么问题,抓住这几次机会,师父也是和我说了很多,从而对整个机房收费系统的业务逻辑更加清楚了.刚开始接触到抽象工厂+配置文件+反射的时候,除了茫然还是茫然,几天下来没有什么成果,登录的主线也没有完全明白

【机房重构】一步一步往上爬——数据库设计

期末考试结束了,寒假全职生活如期而至,终于可以开始全身心的投入我的机房重构了.又是一个新的项目,万事开头难,但不开头更难.自己也只能是一步一步往上爬,机房重构便从数据库设计开始. 回想去年的自考学习,<数据库系统原理>中的知识就可以在机房重构的时候好好应用一把了.第二章的<数据库设计和ER模型>很仔细地教了我们如何进行数据库设计.所以,在参考自考书的基础上,把重构时的数据库全新地设计了一番. 首先明确数据库系统的生存期一般可划分为七个阶段:规划.需求分析.概念设计.逻辑设计.物理设

【机房重构】一步一步往上爬——小问题大收获

机房重构进行了半个月之久了,其中遇到了不少问题,有的调试了很久,有的是因为自己的大意.不管怎样,自己还是通过各种问题,收获了许多,成长了许多.这篇博客主要就是对之前遇到的一些问题的集锦,希望能给大家一些帮助,遇到问题,成功地解决问题. 问题一:缺少参数,在U层传参数的时候少写了一个参数. 解决:根据提示检查U层的该参数,将该参数赋上相应的值. 问题二:进程无法访问文件,文件正由另一个进程使用. 解决:重新生成解决方案,或者是关闭程序,重新启动程序. 问题三:接口的实现错误,类型无法转换,这是因为

【机房重构】一步一步往上爬——企业管理器,好好利用

这么些天,一直在机房重构中.这么些天,从刚开始的迷茫,到已经完全理解七层间的调用,现在是敲代码敲得恶心了.因为自己好像什么都没有做,只是在一遍又一遍的敲重复的代码,有时候,真的不想干了.但不干是不行的,所以,还是想找些其他方法,在挥去一些厌烦情绪的同时,自己也学习些新的东西. 因为太多重复的代码,所以导致了自己不想敲下去,在经过了一些新的尝试后,总算是有种柳暗花明的感觉.那么,本篇博客就将介绍一下在机房收费系统中数据库中的企业管理器的应用,它的强大,以前只是听说或者看过,但自己还没有尝试过.这一

一步一步写算法(之克鲁斯卡尔算法 上)

原文:一步一步写算法(之克鲁斯卡尔算法 上) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     克鲁斯卡尔算法是计算最小生成树的一种算法.和prim算法(上,中,下)按照节点进行查找的方法不一样,克鲁斯卡尔算法是按照具体的线段进行的.现在我们假设一个图有m个节点,n条边.首先,我们需要把m个节点看成m个独立的生成树,并且把n条边按照从小到大的数据进行排列.在n条边中,我们依次取出其中的每一条边,如果发现边的两个节点分别位于两棵树上,

一步一步写算法(之prim算法 上)

原文:一步一步写算法(之prim算法 上) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]     前面我们讨论了图的创建.添加.删除和保存等问题.今天我们将继续讨论图的一些其他问题,比如说如何在图的环境下构建最小生成树.为什么要构建最小生成树呢?其实原理很简单.打个比方,现在某一个乡镇有n个村,那么这n个村肯定是联通的.现在我们打算在各个村之间搭建网线,实现村村通的工程.那么有什么办法可以实现村村互通,同时又使得最后的总距离最小呢?要达

一步一步写算法(之哈夫曼树 上)

原文:一步一步写算法(之哈夫曼树 上) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]       在数据传输的过程当中,我们总是希望用尽可能少的带宽传输更多的数据,哈夫曼就是其中的一种较少带宽传输的方法.哈夫曼的基本思想不复杂,那就是对于出现频率高的数据用短字节表示,对于频率比较低得数据用长字节表示.     比如说,现在有4个数据需要传输,分别为A.B.C.D,所以一般来说,如果此时没有考虑四个数据出现的概率,那么我们完全可以这么分配