We write a lot of code around here. As a result we often run into strange things that seem impossible to figure out. However, over the past 18 years, I have come to realize that with very few, if any, exceptions (no pun intended) the cause of even the most complicated errors can be determined.
Yesterday one of those very odd situations arose. We have a large application that is written in VB.NET and C#. When calling one of the the web methods on a web service written in C# I found that I was getting back nothing instead of the large set of data that was expected. Upon investigation I realized that this was only happening when the code was compiled for release and that the error does not occur in debug mode. Although this is odd, it is not complete unbelievable since it is possible that something was put into the debug only portion of the code that should not have been there. However, this time, that was not the case. The same exact code was getting executed in both modes.
The exception that was occurring was: "Invalid attempt to Read when reader is closed." The code block looked something like this:
Hashtable htObjects =
new Hashtable();
SqlDataReader sdrObjects = null;
try
{
sdrObjects = objectRepository.GetObjects(true);
int intObjectId = 0;
COurObject theObject = null;
if (sdrObjects != null)
{
while (sdrObjects.Read())
{
intObjectId = sdrObjects.GetInt32(1);
if (intObjectId != 0)
{
theObject = new COurObject();
theObject.Load(intObjectId);
AddObject(theObject, htObjects);
}
}
}
}
finally
{
if ((null != sdrObjects) && (false == sdrObjects.IsClosed))
{
sdrObject.Close();
}
}
When I examined the logs I found that the SQL exception was being thrown in the loop over sdrTrades.Read(). So, I added a bunch more log entries to track exactly where things were breaking down since I could not trace things in the debugger. What I found was quite intriguing.
I discovered that if I put a log entry in the finally block that the code worked as expected; even in release mode. This is very odd considering that the actual exception was being thrown in the try block above. As I was explaining this to a friend of mine I told him that it seemed as if this were some sort of code generation error. Then it hit me: this piece of code didn't have a catch block.
So, I went back and added a catch block to the above code and walla! It worked in both debug and release mode. Furthermore, it didn't matter how much or how little error code I put in the catch block or whatever other changes I made to the code. As long as the catch block was in place the code works in both debug and release modes with out any strange errors.
I would really like to go back now and examine the IL code for both of the cases to see exactly what is going on. However, I don't have the time right now to do that because we are trying to get a product out the door. If I find the time in the future I'll post the results of that research here.
So, if you find yourself with a strange SQL exception in your C# code that only happens when you compile for release mode, you might just check to see if you are using a try / finally block without the catch. If you are, this might just be what is happening to you also.