不允许更改'ConnectionString'属性。连接的当前状态是打开的

时间:2009-05-06 10:49:01

标签: asp.net sqlconnection

stackoverflow的第一次使用者,但我已经在Coding Horror上进行了开发。

我对上述错误感到非常头疼。我安装了ELMAH和Google Analytics,随着网站流量的增加,我看到此错误的次数也增加了。

我在整个开发过程中都尽力遵循Microsoft原则:http://msdn.microsoft.com/en-us/library/ms971481.aspx,并且我已根据网络上的多个建议来尽可能地优化我的代码。

我在公共类中使用了SqlConnection;

Public Class pitstop
Public Shared oConn As New System.Data.SqlClient.SqlConnection
    Public Shared Sub doConnect()
    If oConn.State = ConnectionState.Closed Then
        oConn.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings("pitstopConnectionString").ConnectionString
        oConn.Open()
    End If
End Sub
Public Shared Sub doGarbage()
    oConn.Dispose()
End Sub
' /// other code ///
End Class

在我的主要应用程序页面中,我做了同样的事情:

 Private Sub doPump()
    pitstop.doConnect()
    Dim cmd As New System.Data.SqlClient.SqlCommand("doGetCategory", pitstop.oConn)
    Dim dt As New DataTable
    Dim dr As SqlDataReader

    cmd.Parameters.Add("@cat", SqlDbType.Int)
    cmd.Parameters("@cat").Value = CType(Request.QueryString("id"), Integer)

    cmd.CommandType = CommandType.StoredProcedure

    dr = cmd.ExecuteReader()
    While dr.Read()
        If dr.HasRows = True Then
            litCategory.Text = dr("category")
            litCategoryDesc.Text = pitstop.doMakeReadyForHTML(dr("desc"))
        End If
    End While
    cmd = Nothing
    dr.Close()
    pitstop.doGarbage()
End Sub

我一直使用这种方法,而且大部分时间它运作良好,但现在网站变得非常繁忙,戏剧已经开始了!有没有人有任何想法?

我不想重写大量代码,但我愿意接受建议。

:)

克里斯

3 个答案:

答案 0 :(得分:7)

分享您的连接是个问题。

无需共享连接并产生您遇到的问题。 .net的连接池处理幕后真实连接的共享。

只需在doPump()

中创建一个新连接
Private Sub doPump()
    Using Dim conn As New SqlConnection(ConfigurationManager.ConnectionStrings("pitstopConnectionString").ConnectionString)
        Using Dim cmd As New SqlCommand("doGetCategory", conn)
        cmd.CommandType = CommandType.StoredProcedure
        cmd.Parameters.AddWithValue("@cat", CType(Request.QueryString("id"), Integer))
        conn.Open()
        Using Dim dr as SqlDataReader = cmd.ExecuteReader()
            While dr.Read()
                    litCategory.Text = dr("category")
                    litCategoryDesc.Text = pitstop.doMakeReadyForHTML(dr("desc"))
            End While
            dr.Close()
        End Using
    End Using
End Sub

答案 1 :(得分:1)

你的代码有这么多的问题我实际上并不知道从哪里开始。

首先,我假设pitstop是实际的类名,这是一个可怕的类名。其次,pitstop.doMakeReadyForHTML让我觉得这个类包含了各种真正属于那里的功能。

第三,最可怕的是,SqlConnection对象是Shared。这就是一个网络应用程序,它本质上是多线程的。

第四,您的数据库访问逻辑位于代码隐藏页面中,这很糟糕。

第五,您没有正确管理资源。如果在调用pitstop.doGarbage()之前发生异常怎么办(顺便说一句糟糕的名字)?连接要么永远不会关闭,要么就会挂起并导致各种错误。

我的建议如下。一般来说,赶上design patternssoftware architecture。然后你会自己看到你所有的问题。接下来,请阅读Patterns of Enterprise Application Architecture:这将为您打造坚实的基础。

就您当前的代码而言:取消Shared您的连接,将您的数据访问逻辑移至单独的类,正确管理资源(请考虑Using语句)。

答案 2 :(得分:0)

我添加了以下代码,从pitstop类中删除了“共享”连接。 Pitstop被称为'pitstop',因为这是项目的名称。它不合适吗?你们使用什么约定?

我已经取消了doGarbage()函数,现在调用连接和一次性'inline',就像这样;

  Private Sub doPump()
    Dim oConn As New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("pitstopConnectionString").ConnectionString)
    Dim cmd As New System.Data.SqlClient.SqlCommand("doGetCategory", oConn)
    oConn.Open()

    Dim dt As New DataTable
    Dim dr As SqlDataReader

    cmd.Parameters.Add("@cat", SqlDbType.Int)
    cmd.Parameters("@cat").Value = CType(Request.QueryString("id"), Integer)

    cmd.CommandType = CommandType.StoredProcedure

    dr = cmd.ExecuteReader()
    While dr.Read()
        If dr.HasRows = True Then
            litCategory.Text = dr("category")
            litCategoryDesc.Text = pitstop.doMakeReadyForHTML(dr("desc"))
        End If
    End While
    cmd = Nothing
    dr.Close()

    oConn.Dispose()
End Sub

这是对的吗?

此外,Anton提到课堂内的功能不正确 - 我会阅读他已经链接的文件 - 但是有没有快速回答为什么它是错的?

非常感谢所有的回复 - 你们都非常乐于助人。

克里斯