What's wrong with this code?
Well, if you see someone post a bug in the newsgroup and you've never seen there name there before, chances are it's not a bug. The signal to noise ratio on alleged bugs is quite low. So, someone posted this today claiming that it's a bug or if it's not, it's a terrible thing that should be documented. I know most of the people that read this blog are pretty astute, so can you spot the bug?
using System;
using System.Threading;
using System.Data;
using System.Data.SqlClient;
namespace SqlCommandBug
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
new BugReproducer().Reproduce();
}
public class BugReproducer {
public static SqlCommand cmd = new SqlCommand();
public static SqlCommand cmd2 = new SqlCommand();
public BugReproducer() {
cmd.CommandText = "Select * from Parameter";
cmd2.CommandText = "Select * from Application_Curve";
}
public void Reproduce() {
for (int i = 0; i < 2; i++) {
new Thread(new ThreadStart(this.DoIt)).Start();
}
}
public void DoIt() {
SqlConnection conn = new
SqlConnection(System.Configuration.ConfigurationSettings.AppSettings["ConnectionString"]);
conn.Open();
SqlTransaction t1 = conn.BeginTransaction();
lock (cmd) {
cmd.Transaction = t1;
cmd.Connection = t1.Connection;
IDataReader reader = cmd.ExecuteReader();
while (reader.Read());
reader.Close();
}
lock (cmd2) {
cmd2.Transaction = t1;
cmd2.Connection = t1.Connection; //Note from Bill - this is the supposed “Bug“ because it throws an exception
IDataReader reader2 = cmd2.ExecuteReader();
Thread.Sleep(3000);
while (reader2.Read());
reader2.Close();
}
t1.Commit();
}
}
}
}
Now the 'solution' of course that he found was that if he sets the connection and command to null in between them and reinstantiates everything, the problem is fixed. Here's a quote “It seems this either is a bug or if not, the documentation should be updated to say to explicitly set the Transaction and Connection properties of the command to null after the Reader is closed...”
Yes my friends, setting the transaction to null before calling .Commit is the 'solution' hence it's a bug and Microsoft f****ed up by not documenting it.
In the context of the code, it would seem like a Dad yelling at God because he didn't get a warning message when his son was born telling him that leaving the keys to the new Porsche, the Amex card and a stocked liquor cabinet when the kid's 16 years old, before leaving for the weekend , may not be a good idea. Yessir, let me gas the old 911 up and make sure I pay off the balance on the Amex, and oh yes, maybe I should hit the liquor store and load up on everything before leaving.