Пользовательские данные ASP.net получают перекрестки между пользователями, получающими доступ к объектам - PullRequest
5 голосов
/ 05 января 2010

Это довольно странно. Я ищу идеи о том, как задать правильный вопрос так же, как и реальное решение.

У меня есть веб-сайт, и у нас просто огромный скачок трафика. Теперь внезапно мы получаем ошибки параметра sql влево и вправо. Мы перешли на новый сервер sql несколько недель назад, и все было в порядке, но добавленный трафик, похоже, нам мешает.

У меня есть класс доступа к данным, который вызывается, когда каждый пользователь пытается войти в систему. Он выполняет несколько задач, прежде чем, наконец, обновит дату последнего входа пользователей и отправит их в раздел администрирования.

То, что я вижу из журналов трассировки, показывает, что при входе в систему первые несколько задач используют мои данные (скажем, user = birk pass = word). Но в какой-то момент класс accessor начинает отправку данных от кого-то еще, кто пытается войти (скажем, user = abcxyz)

Каждое подключение к серверу закрывается, когда мы закончим с ним. Я обнуляю все объекты доступа, когда закончу с ними. Но почему-то разные пользовательские данные из разных сессий попадают в экземпляры объекта других людей.

Я не использую сессию / приложение / кэш / viewstate для хранения объектов, поэтому я не очень понимаю, как они могут редактировать друг друга ... Просто очень странно, и я не уверен, как вообще заняться исследованием проблема.

Это примерно класс доступа ... Я обрезал некоторые части, которые не были связаны с проблемой

Imports Microsoft.VisualBasic
Imports System.Data
Imports System.Data.SqlClient
Imports System.Text.RegularExpressions
Imports System.Text
Imports System.IO

Namespace ABC
    Public Class DataAccess
        Public Class SQL
            Dim objConnection As SqlConnection
            Dim objAdapter As SqlDataAdapter
            Dim objDataset As DataSet
            Dim objTable As DataTable
            Dim strSQL As String
            Dim strCommandType As String
            Shared sqlparams As List(Of param)
            Public params As New Parameters
            Shadows Application As HttpApplicationState = HttpContext.Current.Application
            Shadows Server As HttpServerUtility = HttpContext.Current.Server
            Shadows Response As HttpResponse = HttpContext.Current.Response
            Shadows Session As HttpSessionState = HttpContext.Current.Session

            Public Sub New()
                Connection()
            End Sub

            Public Sub New(ByVal startingSql As String)
                Connection()
                sql = startingSql
            End Sub

            Private Sub Connection()
                sqlparams = New List(Of param)
                objConnection = New SqlConnection(ConfigurationManager.ConnectionStrings("sqlServerProd").ConnectionString)
            End Sub

            Public Function DataNQ(ByVal type As CommandType, Optional ByVal query As String = "") As Boolean
                If query <> "" Then
                    sql = query
                End If
                Dim objCommand As SqlCommand
                Try
                    objConnection.Open()
                Catch ex As Exception
                    objConnection.Close()
                    objConnection.Open()
                End Try
                objCommand = New SqlCommand(sql, objConnection)
                objCommand.CommandType = type
                Dim cmd As New SqlCommand
                HttpContext.Current.Trace.Warn(sql)
                'HttpContext.Current.Trace.Write("Adding " & sqlparams.Count & " parameters")
                HttpContext.Current.Trace.Warn(params.writeParams)
                If sqlparams.Count > 0 Then
                    For Each p As param In sqlparams
                        Dim sparam As SqlParameter = p.makeParam
                        HttpContext.Current.Trace.Write(sparam.DbType.ToString, sparam.ParameterName & "=" & sparam.Value)
                        objCommand.Parameters.Add(p.makeParam)
                    Next
                    sqlparams = New List(Of param)
                End If
                HttpContext.Current.Trace.Warn("Successfully added " & objCommand.Parameters.Count & " parameters")
                HttpContext.Current.Trace.Warn(params.writeParams)

                '-- Create a SqlParameter object to hold the output parameter value
                Dim paramRetVal As New SqlParameter("@RETURN_VALUE", SqlDbType.Int)
                '-- Must set .Direction as ReturnValue
                paramRetVal.Direction = ParameterDirection.ReturnValue
                '-- Finally, add the parameter to the Command's Parameters collection
                objCommand.Parameters.Add(paramRetVal)
                '-- Call the sproc...
                Dim reader As SqlDataReader = objCommand.ExecuteReader()
                'Now you can grab the output parameter's value...

                Dim intRetVal As Integer = Convert.ToInt32(paramRetVal.Value)
                If intRetVal = 0 Then
                    objConnection.Close()
                    objCommand = Nothing
                    reader = Nothing
                    Return True
                Else
                    objConnection.Close()
                    objCommand = Nothing
                    reader = Nothing
                    Return False
                End If
                objConnection.Close()

            End Function

            Public Sub freeResources()
                sqlparams = Nothing
                params = Nothing
                objConnection = Nothing
                objAdapter = Nothing
                objDataset = Nothing
                objTable = Nothing
                strSQL = Nothing
                strCommandType = Nothing
            End Sub

        Public Sub add(ByVal parameterName As String, ByVal dbType As System.Data.SqlDbType, ByVal size As Integer, ByRef value As Object)
            HttpContext.Current.Trace.Write("adding param name/type/size/value", parameterName & " " & value)
            Dim p As param
            p = New param(parameterName, dbType, size, value)
            p.Value = value
            sqlparams.Add(p)
        End Sub

            Private Class param
                Public name As String = Nothing
                Public size As Integer = Nothing
                Public type As System.Data.SqlDbType = Nothing
                Public value As Object = Nothing
                Public Function makeParam() As SqlParameter
                    HttpContext.Current.Trace.Warn("before make param name=" & name & " type=" & type.ToString & " value=" & value)
                    Dim p As New SqlParameter(name, type)
                    If size <> Nothing Then
                        p.Size = size
                    End If
                    p.Value = value
                    HttpContext.Current.Trace.Warn("after make param name=" & p.ParameterName & " type=" & p.DbType.ToString)
                    Return p
                End Function

        Public Sub New(ByVal pname As String, ByRef ptype As System.Data.SqlDbType, ByRef val As Object)
            'HttpContext.Current.Trace.Write("new param object name/type/value name=" & pname & " type=" & ptype.ToString)
            name = pname
            type = ptype
            value = val
            'HttpContext.Current.Trace.Warn("added param name=" & name & " type=" & type.ToString)
                End Sub
            End Class


        End Class
    End Class

ЛЮБЫЕ идеи или мысли были бы великолепны. Спасибо

Ответы [ 3 ]

7 голосов
/ 05 января 2010

Ваш sqlparams As List(Of param) объявлен как Shared. Это означает, что в памяти только один его экземпляр.

Каждая ссылка на него с каждой созданной страницы - с использованием одного и того же экземпляра из sqlparams.

Это означает, что один экземпляр вашей страницы заполнил его некоторыми параметрами, а другой экземпляр страницы запускается, вызывает ваш метод Connection() и очищает его. Когда процессор переключается обратно на поток первой страницы, sqlparams теперь является новым (или, что еще хуже, Nothing, если другой поток только что вызвал ваш метод freeResources()).

Ваша страница по сути не является потокобезопасной с этим кодом. Замените все переменные Shared переменными экземпляра, и это должно решить проблемы.

2 голосов
/ 05 января 2010

Если ваш класс SQL создан только для экземпляра и не содержит статических / общих методов, то это не должно быть частью проблемы.

РЕДАКТИРОВАТЬ: Ваша коллекция параметров (sqlparams) имеет значение Shared, что позволяет переходить между экземплярами SQL для их параметров.

1 голос
/ 05 января 2010

статические переменные также вызовут проблемы и будут похожи на Application State .... Я думаю, что Shared похоже на static в C # .... Я думаю, что ваши Shared переменные - ваша проблема. Сделайте их переменными экземпляра, и это должно работать.

...