在学习VB.NET的时候在图书馆借了一本关于VB.NET和数据库的书来看,在这本书中有很多关于VB.NET和数据库交互的知识,但是当时没有研究的特别细,因为那本书非常厚,也就只是混了个眼熟,在我做机房收费系统框架的时候,在思考D层的时候突然一个问题困扰我了,那就是我们的每一个功能几乎都得和数据库打交道,那么我们就得需要写很多的重复代码,在第一做机房的时候也就忍了,那是自己还很嫩,也不知道什么是设计模式?什么是面向对象?只知道把功能实现了就好,但是现在我们学习了很多专业化的知识,如果在出现这么多的重复代码,那是无法接受的,那该怎么办呢?
在这个过程中我重新温习了第一遍机房的每一个功能是怎么和数据库大交到的,得出这么一个结论,大概有四种情况如下:
1、带有参数的查询操作,返回值为受影响的行数。
例如:验证用户名是否存在,卡号是否存在等
2、没有参数的查询操作,返回值为受影响的行数
例如:查询基本数据表中的数据
3、带有参数的非查询操作(增、删、改)操作,返回值为DataTable(数据表)
例如:在下机的时候更新上记录表,在退出系统是更新教师值班表等
4、没有参数的非查询操作(增、删、改)操作,返回值为DataTable(数据表)
例如:在退卡的时候删除学生表中的记录
既然我们现在已经抽象出了这么四类,那么我们也就自然想到把这些方法封装起来,当我们需要和数据库交互的时候直接调用即可,当我想到这时候,感觉突然兴奋了一下,因为曾经见到过这么个东西,那就是Sqlhelper类,于是我就在网上查了关于这个类的东西,刚一开始想从网上下载源码,就可以不用自己去写了,但是考虑到以后调错的问题,最后决定还是自己写一个属于自己的Sqlhelper类!
下面看看我封装的第一版,给大家展示一个方法:
Public Shared Function ExecSelect(ByVal cmdTxt As String, ByVal cmdType As CommandType, ByVal paras As SqlParameter()) As DataTable Dim strConnStr As String = System.Configuration.ConfigurationManager.AppSettings("ConnStr") '定义一个数据库连接对象 Dim conn As SqlConnection = New SqlConnection(strConnStr) Dim cmd As New SqlCommand '定义一个命令对象 Dim adataset As DataSet Dim adaptor As SqlDataAdapter '定义一个适配器对象 cmd = New SqlCommand(cmdTxt, conn) adaptor = New SqlDataAdapter(cmd) adataset = New DataSet cmd.CommandType = cmdType cmd.Parameters.AddRange(paras) Try '打开数据库连接 If conn.State = ConnectionState.Closed Then conn.Open() End If '填充数据集 adaptor.Fill(adataset) Catch ex As Exception MsgBox(ex.Message, , "数据库操作") Finally
<span style="font-family: KaiTi_GB2312;"> '关闭数据库连接 </span>
If conn.State = ConnectionState.Open Then conn.Close() End Try Return adataset.Tables(0) End Function在开始我就像上面这样一个一个的封装,但是在我封装的过程中发现这四个方法里面仍然有很多的重复代码,像开始得定义和数据库的打开和关闭等操作,于是我就把这个四个方法再次把一些公共的部分用全局变量给代替了,这样式我的代码看起来更加清晰了很多,下面和大家分享一下我的 第二版代码:
'********************************************** '说明: 用于封装增 删 改 查 的 操作,在DAL层用的时候直接调用即可 '命名空间:SqlHelper '机器名称:晓 '创建日期:2014/12/15 16:41:31 '作者:郑浩 '版本号:V1.00 '********************************************** Imports System.Data Imports System.Data.SqlClient Imports System.Configuration ’我还需要在GUAN Public Class SqlHelper '定义全局变量变量,获得数据库的连接字符串 Private Shared ReadOnly strConnection As String = ConfigurationManager.AppSettings("ConnStr") '定义全局变量,设置连接 Shared conn As SqlConnection = New SqlConnection(strConnection) '定义全局cmd命令 Shared cmd As New SqlCommand ''' <summary> ''' 执行非查询操作(增删改)有参数, ''' </summary> ''' <param name="cmdText">执行增删改查SQL语句或者存储过程</param> ''' <param name="cmdType">命令类型文本或者是存储过程</param> ''' <param name="paras">参数数组,无法确认有多少参数</param> ''' <returns></returns> ''' <remarks></remarks> Public Shared Function ExecuteNoQuery(ByVal cmdText As String, ByVal cmdType As CommandType, ByVal paras As SqlParameter()) As Integer '将传入的值,分别为cmd的属性赋值 Dim result As Integer '定义变量用来存放执行的结果 cmd.Parameters.AddRange(paras) '将参数传入 cmd.CommandType = cmdType '设置一个值,解释cmdText cmd.Connection = conn '设置连接,全局变量 cmd.CommandText = cmdText '设置查询的语句 Try conn.Open() '打开连接 result = cmd.ExecuteNonQuery() '执行增删改操作 cmd.Parameters.Clear() '清除参数 Catch ex As Exception MsgBox(ex.Message, , "数据库操作") '如果出错,返回0 Finally '关闭数据连接 Call CloseConn(conn) Call CloseCmd(cmd) End Try Return result '返回受影响的行数 End Function ''' <summary> ''' 执行增删改三个操作,(无参) ''' </summary> ''' <param name="cmdText">执行增删改查SQL语句或者存储过程</param> ''' <param name="cmdType">命令类型文本或者是存储过程</param> ''' <returns>Interger,受影响的行数</returns> Public Shared Function ExecAddDelUpdateNo(ByVal cmdText As String, ByVal cmdType As CommandType) As Integer '为要执行的命令cmd赋值 cmd.CommandText = cmdText cmd.CommandType = cmdType cmd.Connection = conn cmd.Connection = conn Dim result As Integer '执行操作 Try conn.Open() result = cmd.ExecuteNonQuery() Catch ex As Exception MsgBox(ex.Message, , "数据库操作") Finally Call CloseConn(conn) Call CloseCmd(cmd) End Try Return result '返回受影响的行数 End Function '''' <summary> '''' 执行查询的操作,(有参),参数不限 '''' </summary> ''' <param name="cmdText">执行增删改SQL语句或存储过程</param> ''' <param name="cmdType">文本类型或存储过程</param> ''' <param name="paras">传入的参数</param> ''' <returns>返回为DataTable</returns> ''' <remarks></remarks> Public Shared 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(ex.Message, , "数据库操作") 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></remarks> Public Shared 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></remarks> Public Shared 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></remarks> Public Shared Sub CloseCmd(ByVal cmd As SqlCommand) If Not IsNothing(cmd) Then '如果cmd命令存在 cmd.Dispose() '销毁 cmd = Nothing End If End Sub End Class以上是我根据书中对SqlHelper类的实例的介绍和实例,封装出了这么一个稚嫩的类,这个类在以后的使用中我会不断的完善,在机房收费系统重构的时候感觉足可以应付!
小结
当我们在一遍一遍的敲重复代码的时候,我们就应该停下来想想解决办法,不能盲目的敲代码,尤其是重构这个过程,因为在之前我们学习了很多的新的理论知识,想设计模式,数据库中的一些操作——触发器,存储过程等,有很多方法可以让我们避免重复代码,这样不单是使我们的代码更加清晰,更是我们走向专业化的一个过程,所以我们在重构的时候一定要多思考,让我们前面的理论知识更加灵活的运用到重构当中!