У меня есть 2 фрагмента кода, которые, кажется, испытывают то, что можно описать только как проблемы с многопоточностью.
Я не верю, что написал какой-либо многопоточный код, но мой код выполняется внутриконтекст веб-сервера и, следовательно, многопоточность по сути является частью экосистемы.
Код основан на SQL с использованием ADO.Net.
(Примечание: я ценю потенциал дляАтаки SQL-инъекций, но сейчас давайте предположим, что это решается, потому что SQL для этих команд SQL не может напрямую зависеть от пользовательского ввода)
GetField принимает SQLConnection и некоторый SQL.
- Предполагается, что SQL структурирован как «Выбрать top 1 SomeField from SomeTable».
- Создает SQLCommand вокруг этого SQL
- Выполняет функцию ExecuteScalar команды.
- Возвращает значение, предоставленное ExecuteScalar
GetRecord аналогичным образом принимает SQLConnection и некоторый SQL.
- Предполагается, чтоSQL структурирован как «Выберите SomeFields из SomeTable».
- Выполняет функцию ExecuteReader команды.
- Он анализирует результат, предоставленный ExecuteReader, в известную структуру
- Возвращает известную структуру
Проблема У меня естьчто время от времени функция ExecuteReader в GetRecord, похоже, извлекает результат, который можно ожидать от 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