这是我在DAL中的代码示例。对数据库存储过程的所有调用都是以这种方式构造的,并且没有内联SQL。

Friend Shared Function Save(ByVal s As MyClass) As Boolean

    Dim cn As SqlClient.SqlConnection = Dal.Connections.MyAppConnection
    Dim cmd As New SqlClient.SqlCommand

    Try
        cmd.Connection = cn
        cmd.CommandType = CommandType.StoredProcedure
        cmd.CommandText = "proc_save_my_class"

        cmd.Parameters.AddWithValue("@param1", s.Foo)
        cmd.Parameters.AddWithValue("@param2", s.Bar)

        Return True

    Finally
        Dal.Utility.CleanupAdoObjects(cmd, cn)
    End Try

End Function


这是Connection工厂(如果我使用正确的术语):

Friend Shared Function MyAppConnection() As SqlClient.SqlConnection

    Dim cn As New SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("MyConnectionString").ToString)
    cn.Open()

    If cn.State <> ConnectionState.Open Then
        ' CriticalException is a custom object inheriting from Exception.
        Throw New CriticalException("Could not connect to the database.")
    Else
        Return cn
    End If

End Function


这是Dal.Utility.CleaupAdoObjects()函数:

Friend Shared Sub CleanupAdoObjects(ByVal cmd As SqlCommand, ByVal cn As SqlConnection)
    If cmd IsNot Nothing Then cmd.Dispose()
    If cn IsNot Nothing AndAlso cn.State <> ConnectionState.Closed Then cn.Close()
End Sub


我收到很多“超时到期。在操作完成之前超时的时间,或者服务器没有响应。”用户报告的错误消息。应用程序的DAL打开一个连接,读取或保存数据,然后关闭它。没有连接永远处于打开状态-故意!

在承载SQL Server 2000的Windows 2000 Server上,没有明显的迹象表明存在问题。事件日志中没有任何内容,SQL Server日志中没有任何内容。

超时随机发生-我无法复制。它仅在系统中只有1到5个用户的情况下发生。系统中大约有50位用户也会发生这种情况。对于所有数据库,通过Performance Monitor与SQL Server的连接最多为74个。

超时发生在代码中,该代码既保存到应用程序的不同部分中,又从其中读取。堆栈跟踪不会指向一个或两个有问题的DAL函数。它发生在许多不同的地方。

我的ADO.NET代码似乎可以泄漏连接吗?我已经仔细研究了一下,并且已经读到,如果连接池已满,则可能会发生这种情况。但是,我没有明确设置任何连接池。我什至尝试增加连接字符串中的连接超时,但是超时发生在300秒(5分钟)值之前很久:

<add name="MyConnectionString" connectionString="Data Source=MyServer;Initial Catalog=MyDatabase;Integrated Security=SSPI;Connection Timeout=300;"/>


关于导致这些超时问题的原因,我已经一头雾水。任何想法表示赞赏。

编辑:这是一个WinForms应用程序。

最佳答案

here


与Finalize不同,开发人员应显式调用Dispose以释放非托管资源。实际上,您应该在实现该对象的任何对象上显式调用Dispose方法,以释放该对象可能对其持有引用的所有非托管资源。


SqlConnectionSqlCommandSqlDataReader等...全部实现IDisposable。如果将所有这些实例包含在Using块中,则会自动调用Dispose,连接将被关闭,并且您不必担心此类问题。启动Reflector,看看自己:(SqlConnection.Dispose

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}


这也使代码更短,因为您不必手动添加Final块来清理ADO.NET对象。

Using connection As SqlConnection("your connection string")
    Using command As New SqlCommand("your sql", connection)
        connection.Open()
        Using dataReader As SqlDataReader = command.ExecuteReader()
            'Your stuff here
        End Using
    End Using
End Using


使用Using方法会强制您将ADO.NET对象保持在本地,这对我来说是一件好事。

10-06 07:22
查看更多