Bir*_*irk 5 vb.net asp.net multithreading object sqlparameter
这有点奇怪.我正在寻找关于如何提出正确问题的想法,因为我是一个真正的解决方案.
我有一个网站,我们的流量大幅增加.现在突然间我们得到左右sql参数错误.几个星期前我们切换到一个新的SQL服务器,一切都很好,但增加的流量似乎打破了我们.
我有一个数据访问类,每个用户尝试登录时调用.在最终更新用户上次登录日期并将其转发到管理部分之前,它会运行多个任务.
我从跟踪日志中看到的内容表明,当我登录时,前几个任务正在使用我的数据(比方说user = birk pass = word).但是在某些时候,访问者类开始从试图登录的其他人发送数据(比方说user = abcxyz)
当我们完成它时,我们对服务器的每个连接都会关闭.当我完成它们时,我将所有的访问器对象归零.但不知何故,来自不同会话的不同用户数据正在进入对象的其他人群实例.
我没有使用session/application/cache/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
Run Code Online (Sandbox Code Playgroud)
任何想法或想法都会很棒.谢谢
你sqlparams As List(Of param)
宣布为Shared
.这意味着它只在内存中创建了一个实例.
从每一个实例化的页面,它的每一个参考使用同一个实例的sqlparams
.
这意味着您的页面的一个实例已使用一些参数填充它,并且页面的某些其他实例启动,调用您的Connection()
方法并清除它.当处理器切换回第一页的线程时,sqlparams
现在是新的,(或者更糟糕的是,Nothing
如果另一个线程只调用你的freeResources()
方法).
使用此代码,您的页面本质上是非线程安全的.Shared
用实例变量替换所有变量,它应该解决问题.