Не разрешено изменять свойство «ConnectionString». Текущее состояние соединения открыто - PullRequest
1 голос
/ 06 мая 2009

Первый пользователь 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

Я использовал этот метод повсюду, и большую часть времени он работает хорошо, но теперь сайт ужасно занят, драмы начались! У кого-нибудь есть идеи?

Я бы предпочел не переписывать горы кода, но я открыт для предложений.

:)

Chris

Ответы [ 3 ]

7 голосов
/ 06 мая 2009

Совместное использование ваших соединений является проблемой.

Нет необходимости делиться связями и создает проблемы, которые вы испытываете. .net пул соединений обрабатывает совместное использование real соединений за сценой.

Просто создайте новое соединение в 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 голос
/ 06 мая 2009

Есть так много проблем с вашим кодом, что я даже не знаю, с чего начать.

Прежде всего, я предполагаю, что pitstop - это настоящее имя класса, которое ужасно. Во-вторых, pitstop.doMakeReadyForHTML заставляет меня думать, что этот класс содержит все виды функций, которые на самом деле не принадлежат ему.

В-третьих, и самое ужасное, что ваш SqlConnection объект - Shared. И это в веб-приложении, которое по своей природе является многопоточным.

В-четвертых, ваша логика доступа к базе данных находится на вашей странице с выделенным кодом, что плохо.

В-пятых, вы не управляете своими ресурсами должным образом. Что если исключение произойдет до вызова pitstop.doGarbage() (кстати, ужасное имя)? Соединение либо никогда не закроется, либо будет зависать и вызывать всевозможные ошибки.

Я предлагаю следующее. Познакомьтесь с шаблонами проектирования и с архитектурой программного обеспечения в целом. Тогда вы сами увидите все свои проблемы. Далее прочитайте Шаблоны архитектуры корпоративных приложений : это даст вам прочную основу для построения.

Что касается текущего кода: un Shared ваше соединение, переместите логику доступа к данным в отдельный класс, правильно управляйте ресурсами (подумайте , используя оператор ).

0 голосов
/ 06 мая 2009

Я добавил следующий код, удалив соединение «shared» из класса 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

Это правильно?

Кроме того, Антон отметил, что функциональность в классе является неправильной - я прочитаю и документы, на которые он ссылался, - но есть ли быстрый ответ на вопрос, почему это неправильно?

Большое спасибо за все ответы - вы все очень помогли.

Chris

...