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

	机房重构开始已经一个多星期了,从最开始的理解登录到现在已经成功完成至少一次的“增”、“删”、“改”、“查”的操作,现在在七层的这个大环境下,从最开始的奄奄一息,终于变得生龙活虎起来了。
	之前总是听师哥师姐们说,敲完登录一条线了,后面就会很顺利了。可是,从我来说,事实并非如此。然而,磕磕绊绊,四个字足以形容我的这些天。不过,我心态好,我可以忍受一个人花时间调代码的孤独,再说,我也可以找小伙伴、找师父帮助我,我有什么理由不成功。
	我们在第一次机房收费系统的时候,就有很深的体会:完成了一次增删改查的操作,后面的路就平坦许多。而在机房重构中,这样的体会依旧出现了,只不过我出现的时间晚些,别人在敲完登录之后就有体会了,而我是在自己一次次摸索之后,完成了一些其他的功能,才有所体会的。
	下面就开始进入正题,和大家一起来看看,在七层中的那些事。
	首先说说,“增”、“删”、“改”、“查”。这四个对数据库的操作,思路都是一样的。总结来说,就是以下四条:
	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-08-24 17:47:32

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

【.NET机房重构】——再看抽象工厂加反射实现登录

纯三层的机房重构终于敲完了,但是还需要加设计模式,这又是一道难题.研究了半天的时间,终于对七层的运行步骤熟悉了一些,也对抽象工厂加反射和配置文件了解的更多了一些,下面就看看我的新认识. 这是七层的包图,说是七层,但是七层并不是严格意义上的七层,只不过在三层的基础上加上了工厂.外观和接口,用到设计模式的地方多了自然就形成了一层,所以就有了现在的七层. 各层代码 界面层 分层之后界面层的功能很简单,不能再有逻辑判断,可以有些简单的是否为空或者是否为数字等. <span style="font-

【机房重构】——错误中成长

背景: 本来系统好好的,但今天一打开:180多个错.天呐~~~一下就晕了.整了不到半个小时,就坐不住了.赶快叫救兵前来助阵.怎么办,马上就验收了,真的有些心慌了~~~ 问题 虽然看上去有小200个错,但错误类型就两个:(但没来得及截图,下次遇到问题,先截图留念,有图有真相) 问题一:找不到dll文件 这类问题后来我了解到,有这几个原因: 1:DLL文件名与加载时的DLL文件名不一致. 2:DLL文件根本不存在,即出现丢失情况,或没有生成,或生成路径错误. 3:加载DLL路径错误,即DLL文件存在

史上最简洁的向上取整(机房重构知识点总结)

在机房收费系统的基本数据设定中,有一个单位递增时间,这就需要我们满足如下需求: 假如递增单位时间是5,那么需要实现如下的效果: 5-->5 6-->10 7-->10 11-->15 我们一步一步来,先看一个简单的例子: 2.0-->2 2.1-->3 2.4-->3 2.6-->3 我开始用的取整,然后加1,结果带有小数的可以达到目的,但这会让2.0变为3,怎么办呢?abs(int(-x)),先转换为负数,取整后再变为正数即可.因为int(),会让一个浮点

在Linux上安装Oracle RAC 12 c(12.1) 虚拟机,一步一步向导

Oracle RAC 12 c(12.1)在Linux上安装虚拟机,一步一步向导 今天我们将看到如何安装 12 c版本1 RAC(真正的应用程序集群)数据库2 Linux 64位的虚拟机 使用VMWare或Oracle VirtualBox. 甲骨文的“c”12 c代表“ 云 ” 有一些重要和有趣的变化时安装12 c相比11 g RAC. 甲骨文似乎增加了很多新的有趣的特性在12摄氏度. 请注意,我们需要2虚拟机各有3 GB内存. 所以如果你有足够的记忆你的笔记本电脑/ PC机或服务器上,那么你

一步一步学ZedBoard &amp; Zynq(七):制作ZedBoard上linux根文件系统(ramdisk)

一步一步学ZedBoard & Zynq(七):制作ZedBoard上linux根文件系统(ramdisk) 网址:http://xilinx.eetrend.com/blog/3935 Digilent的OOB设计给出了一个ZedBoard上完整的运行的linux系统所需要的所有文件,包括配置FPGA的bit文件. 配置ARM PS系统的First-Stage boot loader(FSBL)和引导linux需要的Second-Stage boot loader(SSBL).Linux内核z

一步一步教你将开源项目上传到jcenter

最近闲着看了一下jcenter的使用,也想将自己使用频率比较高的东西抽成类库,然后通过compile来使用,提高开发效率,本来以为挺简单的,但是网上介绍的比较模糊,很多博客也比较老了,不适用,花了我一天的时间,还是走了很多弯路,这里记录下来,希望能帮助到小伙伴们,现在觉得还是挺简单的.第一步:首先是注册,这就是我踩的最大的一个坑,导致我一天都没有上传成功.网上说的都是去jcenter的网站上注册就可以,其实不然,英文好的最好去看英文文档,一步一步来操作.个人正确的注册地址:https://bin

【新手出发】从搭虚拟机开始,一步一步在CentOS上跑起来.Net Core程序

文章背景 微软6月26号发布core 1.0版本后,园子里关于这方面的文章就更加火爆了,不管是从文章数量还是大家互动的热情来看,绝对是最热门的技术NO.1.我从去年底开始接触.net core到现在也大半年了,一直停留在浏览各种帖子上,偶尔新建个项目敲几行代码练习一下.可是对于core最大的卖点——跨平台,一直没法实际体验一回,因为压根没接触过Linux,完全不会那些命令,甚至虚拟机都没玩过?,想在Linux上实战操作一下可想有多困难.虽然园子里很多文章都有教程,但大神们一开始直接就上各种命令代

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

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

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

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