Timeout not being honoured in connection string - sql-server

I have a long running SQL statement that I want to run, and no matter what I put in the "timeout=" clause of my connection string, it always seems to end after 30 seconds.
I'm just using SqlHelper.ExecuteNonQuery() to execute it, and letting it take care of opening connections, etc.
Is there something else that could be overriding my timeout, or causing sql server to ignore it? I have run profiler over the query, and the trace doesn't look any different when I run it in management studio, versus in my code.
Management studio completes the query in roughly a minute, but even with a timeout set to 300, or 30000, my code still times out after 30 seconds.

What are you using to set the timeout in your connection string? From memory that's "ConnectionTimeout" and only affects the time it takes to actually connect to the server.
Each individual command has a separate "CommandTimeout" which would be what you're looking for. Not sure how SqlHelper implements that though.

In addition to timeout in connection string, try using the timeout property of the SQL command. Below is a C# sample, using the SqlCommand class. Its equivalent should be applicable to what you are using.
SqlCommand command = new SqlCommand(sqlQuery, _Database.Connection);
command.CommandTimeout = 0;
int rows = command.ExecuteNonQuery();

Related

"Invalid attempt to read when no data is present.", but "hasrows" is true

I wonder if anyone can shed any light on why I'm not getting data in this piece of code:
Private Sub RecoverUnsentOrderToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles RecoverUnsentOrderToolStripMenuItem.Click
' Find orders for this branch with status = "1" - created but not acked from the server
Dim myxDBReader As SqlDataReader
Dim myxDBcmd As SqlCommand
Dim query As String
query = "select * from orders where branch = #branch and status = 1;"
myxDBCmd = New SqlCommand(query, myDBCnn)
myxDBcmd.Parameters.Add("#branch", SqlDbType.VarChar).Value = BranchCode
myxDBReader = myDBCmd.ExecuteReader
If myxDBReader.HasRows Then
Do While myxDBReader.Read
Stop
Loop
End If
BranchCode and my database connection are public variables. When I run this code, it gets as far as the "Stop" and stops, but when I try to use the results, for example in the immediate window by trying to ? myxdbreader(0).tostring, I'm getting "Invalid attempt to read when no data is present" exceptions. When I hover over myxdbreader to view the results, I get a list of the rows, but cannot see the data in them.
This is inside a reasonably large (for me, but not massive) VB application which executes all manner of queries and retrieves data without any problems. The code is copied and pasted from another section of the code where it works quite well. The database connection is a single one, opened when the application is started and passed around as required. Another part of the application writes into this "orders" table without any problem, using the same database connection.
I have another toolstripmenu function which is identical in every respect except the query, in this case it is simply
select * from linkstatus where id=1
and that has the same issue - stops inside the do while dbreader.read loop so it has obviously found a row, but will not allow me to access the data in the way that I normally do.
Because it gets to the "Stop", I know that HasRows is indeed true, and it appears to have read the first row. The only thing I can see that is different is that this code is run from a Menu that I added to the form today, whereas all the rest of the code is run from a variety of buttons on the main form.
Everywhere I've looked up that error message, it appears to be because people have not executed "Read".
This is vb.net from Visual Studio 2019, accessing SQL Server 2018.
You are using a Public connection object, which as the comments state isn't the way to go. But most importantly, note that only one SqlDataReader can be associated with one SqlConnection, compounding the issue of a single shared connection.
SqlDataReader.Read Method
Only one SqlDataReader per associated SqlConnection may be open at a time, and any attempt to open another will fail until the first one is closed. Similarly, while the SqlDataReader is being used, the associated SqlConnection is busy serving it until you call Close.
It's probable that you already have an open Reader, and that is why you are seeing results for another data set.
As noted in the comments by #jmcilhenny, #Jeroen Mostert and #Jimi the root cause of this was using a single public database connection. I have changed the code now so that it connects and disconnects to the database each time I need to access it using a private connection, and it now works correctly.

ExecuteReader TimeOut solved by changing the name of the stored procedure

This happened to me today.
My MVC.Net application was running fine since few months. Today it caught error when executing this part of code.(this is the simplified version)
var cmd = db.Database.Connection.CreateCommand();
cmd.CommandText = $"mySchema.myStoredProcedureName {param1};
db.Database.CommandTimeout = 0;
db.Database.Connection.Open();
var reader = cmd.ExecuteReader();
Where db is a DbContext EF6.
The timeOut occured on the last line
I tried the syntax "using" no success
I tried also the following, maybe the connection is not opened
while(db.Database.Connection.State != ConnectionState.Open) {
db.Database.Connection.Open(); }
No! success.
The stored procedure returns result in 2 seconds on SSMS.
Finally I created a similar stored procedure with another name
Then it worked.
My question:
- Did MSSQL blackList my stored procedure?
I don't think it was blacklisted. Is it possible that your indexes were in need of a rebuild? In other words the renaming really may not have fixed the problem, but some other sort of SQL Server maintenance behind the scenes did?
My educated guess is the server provider did something to affect you if you did not change any code.

continue with next iteration if foreach loop takes too long

I have a for each loop that pulls queries out of a table with queries.
The loop then executes each query and writes the results to a table.
This works like a charm. I even implemented error-handling for when a query could not be executed (if it for example does have syntax-errors).
But sometimes executing a query will take forever, for example a query with a cross join without proper predicament.
Now I would like to be able to set a max duration on the execution of a query. So that a query will be stopped after an x amount of minutes (if it did not finish by then).
The loop should then continue with the next query.
In other words, an iteration should never take longer than X minutes, after that it should continue with the next iteration.
Any ideas, suggestions?
You CANT set a timeout for the query on the server.
Either you create a client app where you can set a timeout for the sql command
SqlCommand command = new SqlCommand(queryString, connection);
// Setting command timeout to 1 second
command.CommandTimeout = 1;
try {
command.ExecuteNonQuery();
}
Or try this External Tool to monitor query and kill those process when time run out. As mentioned on dba.stackexchange

What is happening in debug compilation that is causing the query to take longer to execute?

ServiceStack 3.9.69 via Nuget using SqlServer OrmLite dialect
I'm attempting to execute a parameterized stored procedure but am noticing an unusual slowness when the compilation mode is set to debug. The method that is slow is ConvertToList below:
Dim result = Db.Exec(Of List(Of Dto.FieldSample))(
Function(cmd)
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "up_GetFieldSample"
cmd.Parameters.Add(New SqlClient.SqlParameter("#uploadID", uploadId))
Dim reader = cmd.ExecuteReader()
Dim converted = reader.ConvertToList(Of Dto.FieldSample)()
Return converted
End Function)
(I know there is a .SqlList extension available, but I tried that first with the same results. I switched to Exec to get a better idea of where the issue was)
The stored procedure returns in 2-3 seconds when executed in non-debug mode, but 15-20 seconds in debug mode. I understand that there is often tracing, etc included in debug compilation but I'm trying to figure out what is actually so slow.
What is happening in debug compilation that is causing the query to take longer to execute?
As I suspected, there is some internal error handling/logging being performed during ConvertToList when it calls PopulateWithSqlReader Source
The underlying issue was a data type mismatch between my POCO (decimal?) and the database (int). It wasn't until I hooked up a LogManager.LogFactory = New ConsoleLogFactory() that I could see that an exception was being thrown internally, logged, then moving on. The 235+ (rows) of exception handling was what was causing the delay.

Return database messages on successful SQL execution when using ADO

I'm working on a legacy VB6 app here at work, and it has been a long time since I've looked at VB6 or ADO. One thing the app does is to executes SQL Tasks and then to output the success/failure into an XML file. If there is an error it inserts the text the task node.
What I have been asked to do is try and do the same with the other mundane messages that result from succesfully executed tasks, like (323 row(s) affected).
There is no command object being used, it's just an ADODB.Connection object. Here is the gist of the code:
Dim sqlStatement As String
Set sqlStatement = /* sql for task */
Dim sqlConn As ADODB.Connection
Set sqlConn = /* connection magic */
sqlConn.Execute sqlStatement, , adExecuteNoRecords
What is the best way for me to capture the non-error messages so I can output them? Or is it even possible?
The number of rows affected is returned through an optional second argument of the Connnection object's Execute method
Dim num As Long
sqlConn.Execute sqlStatement, num, adExecuteNoRecords
MsgBox num & " records were affected"
Besides having a generic error handler in your routines the ADO connection object has an Errors collection. After performing some action check the errors for a count > 0 and if it is you need to iterate the collection and log all the errors. There is a Clear method if you want to continue after logging.
After making a quick test project I found that declaring my variable using WithEvents VB adds the InfoMessage event. I ran a DBCC CHECKDB command and the InfoMessage event fired once. The pConnection variable had 284 errors in it with all the other messages.
note: the Connection.Errors collection is 0 based.
I think the rows affected is a function of the Query Analyzer/Enterprise manager, and not something returned through the API.
If I recall correctly, using classic ADO, we had to do a MoveLast then a MoveFirst to force all of the records to come over the wire, then do a count of the Recordset.
I also remember something about which cursor type being used affecting the count of records coming back.
Other than that, are you trying to grab the print statement... It seems like you are using no stored procedures, so beyond count, what are you expecting to get?

Resources