ASP.net 用户数据在访问对象的用户之间交叉

发布于 2024-08-16 18:31:35 字数 6661 浏览 5 评论 0原文

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

我有一个网站,我们的流量刚刚大幅增加。现在突然间我们左右两边都出现了 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

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

This is kind of a weird one. I'm looking for ideas on how to ask the right question as much as I am an actual solution.

I've got a website and we just had a huge jump in traffic. Now all of the sudden we're getting sql parameter errors left and right. We switched to a new sql server a few weeks ago and everything has been fine but the added traffic seems to be breaking us.

I have a data access class that is called when each user trys to logon. It runs through several tasks before finally updating the users last login date and forwarding them to the administration section.

What I'm seeing from the trace logs suggests that when I'm logging in the first several tasks are using my data (lets say user=birk pass=word). But at some point the accessor class starts sending over the data from someone else who's trying to login (lets say user=abcxyz)

Every connection we make to the server is closed when we're finished with it. I'm nulling out all of the accessor objects when I'm finished with them. But somehow different user data from different sessions are making their way into other peoples instances of the object.

I'm not using session/application/cache/viewstate to store the objects so I'm not really seeing how they could edit eachother... Its just really weird and I'm not sure how to even go about researching the problem.

This is roughly the accessor class... I trimmed out some of the parts that weren't reliant to the issue

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

ANY ideas or thoughts would be great. Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

哽咽笑 2024-08-23 18:31:35

您将 sqlparams As List(Of param) 声明为 Shared。这意味着内存中只创建了一个实例。

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

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

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

You have your sqlparams As List(Of param) declared as Shared. This means that there is only one instance of it created in memory, ever.

Every reference to it from every instantiated page is using the same instance of sqlparams.

This means that one instance of your page has populated it with some parameters, and some other instance of the page starts up, calls your Connection() method, and clears it out. When the processor switches back to the first page's thread, sqlparams is now new, (or even worse, Nothing if another thread just called your freeResources() method).

Your page is inherently non-thread safe with this code. Replace all your Shared variables with instance variables and it should solve the issues.

以可爱出名 2024-08-23 18:31:35

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

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

If your SQL class is instantiated only and contains no static/shared methods, then it shouldn't be a part of the problem.

EDIT: Your params collection (sqlparams) is Shared, which will allow cross-over between instantiations of SQL for their parameters.

少女的英雄梦 2024-08-23 18:31:35

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

static variables will also cause problems and are like Application State....I think Shared is like static in C#....I think your Shared variables is your problem. Make them instance variables and it should work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文