I have some code that looks something like this:
using (SqlConnection sqlCon = new SqlConnection("connection string which includes MultipleActiveResultSets=True")
{
using (SqlCommand sqlCmd1 = new SqlCommand("SELECT * FROM MyTable WHERE ProcessedRslt IS NULL", sqlCon)
{
using (SqlDataReader sqlRdr = sqlCmd1.ExecuteReader())
{
using (SqlCommand sqlCmd2 = new SqlCommand("UPDATE MyTable SET ProcessedRslt = @Result WHERE RecordID = @RecordID", sqlCon)
{
sqlCmd2.Parameters.Add("@RecordID", SqlDbType.Int);
sqlCmd2.Parameters.Add("@Result", SqlDbType.Int);
while (sqlRdr.Read())
{
int result = ProcessRecord(sqlRdr["RecordID"], ...) // <- This function takes a bunch of values from the SqlDataReader, performs some fairly complex operations on them and returns a result indicating success or what type failure was encountered.
sqlCmd2.Parameters["@RecordID"].Value = (int)sqlDataReader["RecordID"];
sqlCmd2.Parameters["@Result"].Value = result;
sqlCmd2.ExecuteNonQuery(); // !!!THIS IS THE LINE I'M CONCERNED ABOUT!!!
}
}
}
}
}
So this code is sitting in a production environment and have been running well for years. But there is the occasional hiccup and lately it's been happening more regularly. The while (sqlRdr.Read()) loop runs smoothly a few thousand times and then out of the blue the sqlCmd2.ExecuteNonuery() line causes a timeout which is caught by my exception handling.
For the life of me I can't figure out why that simple UPDATE statement should time out in SQL, especially when the same statement has just executed successfully a few thousand times without hiccups. I'm not too clued up on Microsoft SQL Server maintenance and I'm wondering if some other process that might be accessing the database and this table in particular might be causing a deadlock or something. I don't have control over (or even perfect knowledge of) what other processes might be accessing the database at what time.
But I would've thought that UPDATE MyTable SET this WHERE that is a pretty straight forward atomic query that shouldnt be affected by other queries run against the DB at the same time? Or could the fact that it sits inside a fairly long running using (SqlDataReader...) block be part of the problem?
If so, what is the idiomatic way of reading a large number of records from a table, performing a task on each one, and then updating each one individually based on the outcome of the task performed? Surely this must be a common use case?
sqlCmd2running on? it isn't shown as running on any connection in the code, in which case no: it won't work; if it issqlCon, then ... this is bad practice; it can work if MARS is enabled, but MARS should virtually never be enabled - a separate connection is preferred (and yes: I see that MARS is enabled in your comment, but...) - so: it should work, but: timeouts will occasionally happen; as for why: you'd need to look at the specific scenario - what locks are taken, serve activity, etc