在最开始做机房收费时自己写了一个SqlHelper,里面有一个关于DataReader的函数ExecuteReader,因为在看VB.NET时那位资深讲师说资料库连线在不用时一定要关闭,这样可以减少资源占用,提高数据库访问效率,所以在ExecuteReader里面我就把Connection给关掉了,如下所示
public shared function ExecuteReader(ByVal CmdType As CommandType, ByVal Cmdtxt As String) as SqlDataReader
Dim cnn As SqlConnection = New SqlConnection(strcnn)
Dim cmd As New SqlCommand()
Dim Reader As SqlDataReader
cmd.CommandType = CmdType
cmd.CommandText = Cmdtxt
Try
If cnn.State = ConnectionState.Closed Then
cnn.Open()
End If
Reader = cmd.ExecuteReader
Catch ex As Exception
Throw New Exception(ex.Message)
Finally
cnn.Close()
End Try
Return Reader
end function
结果在使用时发现提示错误:“连接关闭时,不能执行Read方法”
后来我想起来了,那位资深讲师还说过DataReader的游标在服务器端,执行DataReader.Read方法时数据库连接必须是开着的
如果关闭那么就会出现上面的错误。而DataSet的游标在客户端,数据库连线断开时依然可以对DataSet进行增删改查,于是我想到了下面的方法:
在调用ExecuteReader函数的地方建立一个SqlConnection对象,将它作为参数传递给ExecuteReader函数,在用完DataReader时再关闭SqlConnection对象,如下:
Public Shared Function GetReader(ByVal CmdType As CommandType, ByVal Cmdtxt As String, _
ByVal cnn As SqlConnection) As SqlDataReader
Dim cmd As New SqlCommand()
Dim Reader As SqlDataReader
cmd.CommandType = CmdType
cmd.CommandText = Cmdtxt
cmd.Connection = cnn
Try
If cnn.State = ConnectionState.Closed Then
cnn.Open()
End If
Reader = cmd.ExecuteReader
Catch ex As Exception
Throw New Exception(ex.Message)
Finally
'cnn.Close() 这个地方将cnn.Close()注释掉了,在调用ExecuteReader函数的地方关闭cnn对象
End Try
Return Reader
End Function
调用ExecuteReader函数
dim cnn as new sqlconnection(..........) '在调用ExecuteReader的地方建立connection
dim reader as sqldatareader
reader =ExecuteReader(commandtype.text,strSQL,cnn)
if reader.read then
........
end if
cnn.close ’在调用ExecuteReader函数的地方关闭cnn对象
这样算是解决了问题,但是凡事在使用ExecuteReader的地方都要建立一个connection对象,没有把connection封装在SQLHelper里面好
后来我上网查了一下找到了解决办法,其实很简单,既然微软提供了DataReader,那么它坑定考虑到了这个问题,肯定也有解决办法,办法就是:
把ExecuteReader函数里面的 cmd.ExecuteReader() 改成
cmd.ExecuteReader(CommandBehavior.CloseConnection)
MSDN里面是这样解释cmd.ExecuteReader(CommandBehavior.CloseConnection)的:
“
在执行该命令时,如果关闭关联的
DataReader
对象,则关联的
Connection
对象也将关闭。
只要在调用ExecuteReader函数的地方把reader关掉(reader.close),就可以关闭connection
最后的代码:
public shared function ExecuteReader(ByVal CmdType As CommandType, ByVal Cmdtxt As String) as SqlDataReader
Dim cnn As SqlConnection = New SqlConnection(strcnn)
Dim cmd As New SqlCommand()
Dim Reader As SqlDataReader
cmd.CommandType = CmdType
cmd.CommandText = Cmdtxt
Try
If cnn.State = ConnectionState.Closed Then
cnn.Open()
End If
Reader = cmd.ExecuteReader(CommandBehavior.CloseConnection) ‘这里是最关键的
Catch ex As Exception
Throw New Exception(ex.Message)
Finally
’cnn.Close() 这里不用关闭cnn了,因为在调用ExecuteReader的地方只要关闭相应的reader就可以了
End Try
Return Reader
end function
调用ExecuteReader
reader =ExecuteReader(commandtype.text,strSQL)
if reader.read then
........
end if
reader.close '在这里关闭了reader,同时就关闭了SQLHelper中的connection
只要在cmd.ExecuteReader()内加一个参数”CommandBehavior.CloseConnection“,就可以解决问题了。这样既可以及时关闭数据库连线(在不破坏SQLHelper封装性的前提下),又可以正常使用reader.read(), 真是好啊!