System.InvalidOperationException is thrown when attempting simultaneous calls to ExecuteNonQuery

0.00 avg. rating (0% score) - 0 votes

If you have multiple threads trying to execute an SqlCommand via ExecuteNonQuery using a single SqlConnection object, you may get the following exception:

System.InvalidOperationException: ExecuteNonQuery requires an open and available Connection. The connection’s current state is closed.

The following code replicates the problem:

Dim conn As New SqlConnection(“Data Source=localhost;User Id=sa; Password=; Initial Catalog=test”)

Sub Main()
conn.Open()

For i As Integer = 0 To 1000
Dim th As New Threading.Thread(AddressOf TestSqlThread)
th.Start(i)
NextEnd Sub

Private Sub TestSqlThread(ByVal state As Object)
Console.WriteLine(state)
Dim cmdLocal As New SqlCommand(“INSERT INTO testtable(col1, col2) VALUES(‘H’, ‘Hello2′)”, conn)
cmdLocal.ExecuteNonQuery()
cmdLocal.Dispose()
End Sub

What the above code does is to open a single connection and create multiple threads which call ExecuteNonQuery on the connection which was created. The multiple threads do not wait for each other – they execute concurrently. The previous call to ExecuteNonQuery may not have been finished before the next one comes in. So there may be concurrent attempts to call ExecuteNonQuery to update the database. .NET only supports up to a maximum number of concurrent calls to ExecuteNonQuery on a single SqlConnection object. When the limit is reached, the exception mentioned above is thrown.

A workaround is to use a lock to make sure you call ExecuteNonQuery one after another, and not concurrently:

Dim mylock as new object
Private Sub TestSqlThread(ByVal state As Object)
Console.WriteLine(state)
Dim cmdLocal As New SqlCommand(“INSERT INTO testtable(col1, col2) VALUES(‘H’, ‘Hello2′)”, conn)
Synclock MyLock
cmdLocal.ExecuteNonQuery()
End Synclock
cmdLocal.Dispose()
End Sub

However, this will have a performance impact as the query will be executed one by one and slow down the application. A better alternative would be to create a separate SqlConnection object for each thread that needs to call ExecuteNonQuery.

0.00 avg. rating (0% score) - 0 votes
ToughDev

ToughDev

A tough developer who likes to work on just about anything, from software development to electronics, and share his knowledge with the rest of the world.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>