Не разрешено изменять свойство "ConnectionString". Текущее состояние соединения открыто
Первый раз в работе над stackru, но я следил за его развитием на 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 ответа
Совместное использование ваших связей является проблемой.
Нет необходимости делиться связями и создает проблемы, которые вы испытываете..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
В вашем коде так много проблем, что я не знаю, с чего начать.
Во-первых, я предполагаю, что pitstop
действительно имя класса, которое ужасно. Во-вторых, pitstop.doMakeReadyForHTML
заставляет меня думать, что этот класс содержит все виды функций, которые на самом деле не принадлежат ему.
В-третьих, и самое ужасное, это то, что ваш SqlConnection
объект Shared
, И это в веб-приложении, которое по своей природе является многопоточным.
В-четвертых, ваша логика доступа к базе данных находится на странице с выделенным кодом, что плохо.
В-пятых, вы не управляете своими ресурсами должным образом. Что делать, если исключение происходит до вызова pitstop.doGarbage()
(ужасное имя, кстати)? Соединение либо никогда не закроется, либо будет зависать и вызывать всевозможные ошибки.
Я предлагаю следующее. Познакомьтесь с шаблонами проектирования и архитектурой программного обеспечения в целом. Тогда вы сами увидите все свои проблемы. Далее прочитайте Шаблоны архитектуры корпоративных приложений: это даст вам прочную основу для дальнейшего развития.
Насколько ваш текущий код идет: Un Shared
ваше соединение, переместите логику доступа к данным в отдельный класс, правильно управляйте ресурсами (подумайте с помощью оператора Using).
Я добавил следующий код, удалив соединение "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
Это правильно?
Кроме того, Антон упомянул наличие в классе функциональности как неправильной - я прочитаю также документы, на которые он ссылался, - но есть ли быстрый ответ на вопрос, почему это неправильно?
Большое спасибо за все ответы - вы все очень помогли.
Крис