5

这有点奇怪。我正在寻找关于如何提出正确问题的想法,就像我是一个实际的解决方案一样。

我有一个网站,而且我们的流量有了巨大的增长。现在突然之间,我们左右两边都出现了 sql 参数错误。几周前我们切换到了一个新的 sql 服务器,一切都很好,但增加的流量似乎让我们崩溃了。

我有一个数据访问类,当每个用户尝试登录时都会调用它。在最终更新用户上次登录日期并将他们转发到管理部分之前,它会运行几个任务。

我从跟踪日志中看到的内容表明,当我登录前几个任务时正在使用我的数据(比如说 user=birk pass=word)。但是在某些时候,访问器类开始从其他试图登录的人那里发送数据(比如说 user=abcxyz)

完成后,我们与服务器建立的每个连接都会关闭。当我完成所有访问器对象时,我会将它们清空。但不知何故,来自不同会话的不同用户数据正在进入其他人的对象实例。

我没有使用会话/应用程序/缓存/视图状态来存储对象,所以我并没有真正看到它们如何相互编辑......这真的很奇怪,我什至不知道如何着手研究这个问题。

这大致是访问器类...我删除了一些不依赖于问题的部分

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

任何想法或想法都会很棒。谢谢

4

3 回答 3

7

你有你的sqlparams As List(Of param)声明为Shared。这意味着在内存中只创建了一个它的实例。

每个实例化页面对它的每个引用都使用相同sqlparams.

这意味着您的页面的一个实例已使用一些参数填充它,并且该页面的其他一些实例启动,调用您的Connection()方法并将其清除。当处理器切换回第一页的线程时,sqlparams现在是新的,(或者更糟糕的是,Nothing如果另一个线程刚刚调用了您的freeResources()方法)。

使用此代码,您的页面本质上是非线程安全的。用实例变量替换所有Shared变量,它应该可以解决问题。

于 2010-01-04T21:37:49.263 回答
2

如果您的SQL类仅被实例化并且不包含静态/共享方法,那么它不应该是问题的一部分。

编辑:您的参数集合 ( sqlparams) 是,这将允许其参数的Shared实例化之间交叉。SQL

于 2010-01-04T21:34:54.310 回答
1

静态变量也会导致问题,就像应用程序状态......我认为Shared就像static在 C# 中......我认为你的Shared变量是你的问题。使它们成为实例变量,它应该可以工作。

于 2010-01-04T21:37:28.997 回答