2

Update: Sorry for the delay over the weekend but some updates to your comments: I have updated the stack trace to include the entire stack. As well, the problems still exists when I manually close the reader via DataReader.Close(). The database that I am using is just a Microsoft Access databse. Finally, If I catch the OdbcException, this is the information in the exception:

OdbcException: Data: System.Collections.ListDictionaryInternal
ErrorCode: -2146232009 (Most likely no help)
Errors: System.Data.OdbcErrorCollecion
HelpLink: [blank]
InnerException: [blank]
Message: [blank]
Source: [blank]
TargetSite: Void StatementErrorHandler(RetCode)

End Update.

Is there any reason the OdbcDataReader.Close() method would function normally in Visual Studio when debugging, but would throw an OdbcException on the Close method when the EXE is run outside of Visual Studio?

A little background: I have an application that performs some basic interaction with a database, and I have been interacting with the database by using a standard format (shown below) held in a Database class. This class has been working for around 6 months when recently it started to crash when the program is run from the EXE only. It would throw an unhandled exception OdbcException when the DataReader was closed (at the end of a using statement. Same exception if the Close() method is called). The stack trace for the exception is (with some names changed):

at System.Data.Odbc.CMDWrapper.StatementErrorHandler(RetCode retcode)  
at System.Data.Odbc.CMDWrapper.FreeStatementHandle(STMT stmt)  
at System.Data.Odbc.OdbcDataReader.Close(Boolean disposing)  
at System.Data.Odbc.OdbcDataReader.Dispose(Boolean disposing)  
at System.Data.Common.DbDataReader.Dispose()  
at Namespace.DatabaseManag.Retrieve(String column, String table) in C:\Program\CommonFiles\DatabaseManag.cs:line 81  
at Namespace.Parameters.LoadData() in C:\UserControls\Parameters.cs:line 49  
at Namespace.MainScreen.OnLoad(Object sender, EventArgs e) in C:\Program\MainScreen.cs:line 99  
at System.Windows.Forms.Form.OnLoad(EventArgs e)  
at System.Windows.Forms.Form.OnCreateControl()  
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)  
at System.Windows.Forms.Control.CreateControl()  
at System.Windows.Forms.Control.WmShowWindow(Message& m)  
at System.Windows.Forms.Control.WndProc(Message& m)  
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)  
at System.Windows.Forms.ContainerControl.WndProc(Message& m)  
at System.Windows.Forms.Form.WmShowWindow(Message& m)  
at System.Windows.Forms.Form.WndProc(Message& m)  
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)  
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)  
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

When launched from Visual Studio everything functions normally. It is only when the EXE is ran that this problem occurs. Through a lot of trial and error I was able to remove pieces from the Database class until I could narrow it down between a method that would work and a method that would throw the exception. The only difference between the two methods was an empty catch clause shown below:

Method that does not work:

public List<string> Retrieve(string column, string table)
{
    List<string> Results = new List<string>();
    try
    {
        using (OdbcConnection Conn = new OdbcConnection("DSN=DSNNAME"))
        {
            using (OdbcCommand Command = new OdbcCommand("select " + column + " from " + table, Conn))
            {
                Conn.Open();
                using (OdbcDataReader Reader = Command.ExecuteReader())
                {
                    while (Reader.Read())
                    {
                        Results.Add(Reader.GetString(0));
                    }
                } //This is the line that it will fail on
            }
        }
    }
    finally
    {
    }
    return Results;
}

Method that does work (By works, I mean that the information from the database is still read and returned correctly, but the exception is ignored):

public List<string> Retrieve(string column, string table)
{
    List<string> Results = new List<string>();
    try
    {
        using (OdbcConnection Conn = new OdbcConnection("DSN=DSNNAME"))
        {
            using (OdbcCommand Command = new OdbcCommand("select " + column + " from " + table, Conn))
            {
                Conn.Open();
                using (OdbcDataReader Reader = Command.ExecuteReader())
                {
                    while (Reader.Read())
                    {
                        Results.Add(Reader.GetString(0));
                    }
                }
            }
        }
    }
    catch
    {
    }
    finally
    {
    }
    return Results;
}

I cannot find a reason why this would occur. And when trying to replicate this in a separate project it would not throw the exception which leads me to believe is related to my specific project. However, when the blank catch clause is added into the full Database class, it still throws the exception.

Does anyone know why this is occurring? I'm getting the feeling something is corrupted but reinstalling all relevant applications had no effect.

mdemoret
  • 21
  • 1
  • 5
  • Where abouts is the close method in the functions you posted? Are you sure it's the close method specifically that's causing the problem? – joshhendo Feb 25 '11 at 23:13
  • 1
    Your working method: an extra `catch` is eating your exception. I'd hardly call that "working". – Kirk Woll Feb 25 '11 at 23:14
  • Does the problem also appears when you do not use `using` statement and dispose the objects manually? – Xavinou Feb 25 '11 at 23:14
  • Can you post the full stack trace and exception message (especially if it has a code number?) What database server are you using? – Mike Atlas Feb 25 '11 at 23:27
  • I have updated the post to include the information that you requested. – mdemoret Feb 28 '11 at 16:03

3 Answers3

0

Catch the exception and look at it: catch(Exception ex)

Cosmin
  • 2,365
  • 2
  • 23
  • 29
  • When I catch the exception there is little to no information regarding the exception. I have updated my original post to include the full exception information. – mdemoret Feb 28 '11 at 16:04
0

It's possible there's a race condition going on regarding closing the connection to the access database, which is just a file, especially if you can only reproduce it outside of the development environment runtime, which is probably marginally faster.

What happens if you introduce a small sleep into the code?

using (OdbcDataReader Reader = Command.ExecuteReader())
{
    while (Reader.Read())
    {
        Results.Add(Reader.GetString(0));
    }
    Thread.Sleep(TimeSpan.FromMilliseconds(100));
}

Note, this isn't probably a good "production code" solution, but if it fixes it, perhaps it may be the only fix you can go with. Catching and swallowing the exception most likely burns at least 100ms. If it does, I would leave it in, but also add a specific catch that checks for the expected "innocuous" exception and only swallows it if it is indeed that exact exception, otherwise rethrow it.

Mike Atlas
  • 8,193
  • 4
  • 46
  • 62
0

After much trial and error I was able to finally determine the issue. In the odd chance somebody runs across this problem too, I figured I would answer my own question.

After completely recreating my project and still not able to replicate the error or get any more information than Odbcexception I discovered a program, Application Verifier, (not entirely sure what it does since this computer is shared) was attaching to the process. Every time my project was run outside of Visual Studio, Application verifier was most likely attaching to my exe's process and causing the error. Opening application verifier and deleting the reference to my project's exe and all log files seems to have fixed the issue.

I can see how this could have been possibly causing my error but I have no idea why the DataReader.Close() what the line of code it would error on. If anyone knows and would care to share, I would be interested.

mdemoret
  • 21
  • 1
  • 5