我有两段代码似乎正在经历只能被描述为多线程问题的代码。
我不相信我已经编写了任何多线程代码,但我的代码在网络服务器的上下文中运行,因此多线程基本上是生态系统的一部分。
该代码基于SQL,使用ADO.Net。
(注意:我很欣赏SQL注入攻击的可能性,但是现在让我们假设这是因为这些SQL命令的SQL不能直接受到用户输入的影响)
GetField 采用SQLConnection和一些SQL。
GetRecord 同样采用SQLConnection和一些SQL。
问题我遇到的是,偶尔GetRecord中的ExecuteReader函数似乎正在检索GetField所期望的结果
然后尝试将数据解析为已知结构。
我无法可靠地重现这一点,因此我正在寻求帮助。
有没有人有任何想法可能会发生这种情况?
FWIW我的后端SQL是SQL2008
更新: FWIW,拥有这些方法的对象,有自己的连接字段,初始化为新的SQLConnection对象,该对象本身从中心位置提供连接字符串。
更新:这是我正在谈论的那种DA对象的示例。
Imports System.Data.SqlClient
Public Module SomeModule
Public Function GlobalConnection() As SqlConnection
Return New SqlConnection(GetSQLStringFromConfig())
End Function
End Module
Public Class ExampleDA
Protected Con As SqlConnection
Public Sub New()
Me.Con = GlobalConnection()
End Sub
Public Function GetRecord(ByVal SQL As String) As String()
Dim Close As Boolean = EnsureConnectionOpen(Con)
Dim dc As New SqlCommand(SQL, Con)
Try
Dim DcExecuteReader As SqlDataReader
If Close Then
DcExecuteReader = dc.ExecuteReader(CommandBehavior.CloseConnection)
Else
DcExecuteReader = dc.ExecuteReader()
End If
' ToStringArray doesn't exist but it gets the general point across.
Return DcExecuteReader.ToStringArray()
Catch ex As SqlException
Throw
End Try
End Function
Public Function GetField(ByVal SQL As String, ByVal DefaultValue As Object) As Object
Dim Close As Boolean = EnsureConnectionOpen(Con)
Dim dc As SqlCommand = New SqlCommand(SQL, Con)
Dim Result As Object = GetField(dc, DefaultValue)
If Close Then Con.Close()
Return Result
End Function
Private Function GetField(ByVal Command As SqlCommand, Optional ByVal DefaultValue As Object = Nothing) As Object
Try
Dim ReturnValue As Object
Dim Close As Boolean = EnsureConnectionOpen(Command.Connection)
ReturnValue = Command.ExecuteScalar()
If ReturnValue Is Nothing Then
ReturnValue = DefaultValue
End If
If Close Then
Command.Connection.Close()
End If
If IsDBNull(ReturnValue) Then
Return DefaultValue
Else
Return ReturnValue
End If
Catch ex As Exception
Debug.WriteLine(ex.ToString)
Throw
End Try
End Function
Private Function EnsureConnectionOpen(ByRef Con As SqlConnection) As Boolean
If Con.State <> ConnectionState.Open Then
Con.Open()
Return True
End If
Return False
End Function
End Class
答案 0 :(得分:1)
您如何处理数据库的连接?
一个数据库连接= SQL的一个进程,无论如何都不会共享这些进程。要获得“混合”结果,您需要覆盖共享连接的某些上下文。
答案 1 :(得分:0)
如何在函数之间存储/共享连接?
你在MARS下运行吗?如果没有,请尝试在连接字符串中启用它(MultipleActiveResultSets = True)。
请注意,IIS可能/将在执行期间将执行上下文从一个线程切换到另一个线程。因此,任何共享连接最终将在两个线程之间共享,并且可能会失败。使用MARS和/或明确的新连接应该可以缓解这种情况。
答案 2 :(得分:0)
您必须同时使用一个连接,否则您可能会得到不需要的结果。假设有人在连接上打开一个事务而没有其他功能知道?
您应该始终调用GetConnection,因为后端无论如何都会进行连接池化。因此,在性能方面,它很可能无关紧要。
HTH
马里奥
答案 3 :(得分:0)
GetField( string sqlCommand )
{
SqlConnection conn = new SqlConnection( connectionString );
conn.Open();
try
{
using ( SqlCommand cmd = conn.CreateCommand() )
{
cmd.CommandText = cmd;
cmd.ExecuteScalar();
//here be your code..
}
}
finally
{ conn.Close();
}
}
不要存储连接,不要对它们做任何事情。根据需要打开和关闭,库在幕后执行命令汇集!
HTH
马里奥