Reputation: 683
We're using C# SqlCommand.ExecuteReader()
to issue SQL Server stored procedure and SQL requests inside a transaction.
When the connection is chosen as a deadlock victim, ExecuteReader()
does NOT throw SqlException
with 1205 deadlock code for some commands but DOES for others.
According to MSDN
If a transaction is deadlocked, an exception may not be thrown until Read is called.
Considering that we use SqlCommand
object encapsulated inside our own database request framework, is there a way to always guarantee that the exception is thrown when a deadlock occurs?
We're using .Net 4.5, SQL Server 2008 R2, Visual Studio 2012
Here is a simplified version of our database access framework code:
SqlDataReader DoWork( string sql ) {
...
cmd = new SqlCommand( sql );
SqlDataReader rdr = null;
try {
rdr = cmd.ExecuteReader( CommandBehavior.Default );
} catch (SqlException sqle) {
// Log the error, throw a custom exception, etc.
// if (sqle.ErrorCode == 1205) ...
...
if (rdr != null) {
rdr.Close();
rdr = null;
}
}
// All is well, so just return to caller to consume the result set
return rdr;
}
...
main() {
...
SqlDataReader result = DoWork( "select ...";
if (result.HasRows) { // Check there is data to read...
while (result.Read()) {
...
}
result.Close();
...
}
Upvotes: 3
Views: 1539
Reputation: 171226
I don't know why you are doing this:
if (result.HasRows)
This is not necessary and it prevents the deadlock from appearing:
If a transaction is deadlocked, an exception may not be thrown until Read is called.
Delete that if
. It's a common anti pattern. It's often introduced by people who copy sample code without really understanding what it does.
This in your catch
is also an anti pattern:
if (rdr != null) {
rdr.Close();
rdr = null;
}
Just use using
.
Upvotes: 4
Reputation: 3261
this is the code from that link, Stack wouldnt allow it as an answer
function DoWork() {
using (TransactionScope scope = new TransactionScope(...)) {
cmd = new SqlCommand("select ...");
using (DataReader rdr = cmd.ExecuteReader ()) {
while(rdr.Read()) {
... process each record
}
}
scope.Complete ();
}
}
Upvotes: 0