Метод чтения данных закрывает метод OdbcException - PullRequest
2 голосов
/ 26 февраля 2011

Обновление: извините за задержку на выходные, но некоторые обновления ваших комментариев: я обновил трассировку стека, чтобы включить весь стек.Кроме того, проблемы все еще существуют, когда я вручную закрываю читатель через DataReader.Close ().База данных, которую я использую, - это просто база данных Microsoft Access.Наконец, если я поймаю OdbcException, это информация в исключении:

OdbcException: Data: System.Collections.ListDictionaryInternal
ErrorCode: -2146232009 (скорее всего, не поможет)
Ошибки: система.Data.OdbcErrorCollecion
HelpLink: [пусто]
InnerException: [пусто]
Сообщение: [пусто]
Источник: [пусто]
TargetSite: Void StatementErrorHandler (RetCode)

Завершить обновление.

Есть ли какая-либо причина, по которой метод OdbcDataReader.Close() будет нормально функционировать в Visual Studio при отладке, но будет вызывать исключение OdbcException для метода Close, когда EXE-файл запускается вне Visual Studio?

Немного предыстории: у меня есть приложение, которое выполняет некоторые базовые взаимодействия с базой данных, и я взаимодействую с базой данных, используя стандартный формат (показанный ниже), хранящийся в классе Database.Этот класс работал около 6 месяцев, когда недавно он начал падать, когда программа запускается только из EXE.Было бы выброшено необработанное исключение OdbcException, когда DataReader был закрыт (в конце оператора using. То же исключение, если вызван метод Close ()).Трассировка стека для исключения (с некоторыми измененными именами):

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)

При запуске из Visual Studio все работает нормально.Эта проблема возникает только при запуске EXE.Через много проб и ошибок я смог удалить части из класса Database, пока не смог сузить его между методом, который будет работать, и методом, который вызовет исключение.Единственным различием между этими двумя методами было пустое предложение catch, показанное ниже:

Метод, который не работает:

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;
}

Метод, который работает (Под работами я имею в виду, что информация избаза данных по-прежнему читается и возвращается правильно, но исключение игнорируется):

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;
}

Я не могу найти причину, по которой это может произойти.И при попытке воспроизвести это в отдельном проекте, это не приведет к исключению, которое, как я полагаю, связано с моим конкретным проектом.Однако, когда пустое предложение catch добавляется в полный класс Database, оно все равно выдает исключение.

Кто-нибудь знает, почему это происходит?У меня такое ощущение, что что-то повреждено, но переустановка всех соответствующих приложений не дала результата.

Ответы [ 3 ]

0 голосов
/ 28 февраля 2011

Возможно, существует условие гонки в отношении закрытия соединения с базой данных доступа, которая является просто файлом, особенно если вы можете воспроизводить его только вне среды выполнения среды разработки, которая, вероятно, несколько быстрее.

Что произойдет, если вы введете небольшой код в код?

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

Обратите внимание, что это, вероятно, не хорошее решение для "производственного кода", но если оно исправляет его, возможно, это единственное исправление, с которым вы можете пойти.Поймать и проглотить исключение, скорее всего, ожоги не менее 100 мс.Если это произойдет, я бы оставил его, но также добавил бы особый улов, который проверяет ожидаемое «безобидное» исключение и проглатывает его, только если это действительно именно это исключение, в противном случае его отбрасывают.

0 голосов
/ 09 марта 2011

После долгих проб и ошибок я смог наконец определить проблему.По случайной случайности, когда кто-то сталкивается с этой проблемой, я решил ответить на свой вопрос.

После того, как я полностью воссоздал свой проект и все еще не смог воспроизвести ошибку или получить больше информации, чем Odbcexception, я обнаружил, что программа Application Verifier (не совсем уверенная в том, что она делает, так как этот компьютер используется совместно) подключается кпроцесс.Каждый раз, когда мой проект запускался за пределами Visual Studio, верификатор приложений, скорее всего, подключался к процессу моего exe-файла и вызывал ошибку.Открытие верификатора приложения и удаление ссылки на exe-файл моего проекта и все файлы журнала, похоже, устранили проблему.

Я могу видеть, как это могло быть причиной моей ошибки, но я понятия не имею, почему DataReader.Close (), в какой строке кода это будет с ошибкой.Если кто-то знает и хотел бы поделиться, мне было бы интересно.

0 голосов
/ 26 февраля 2011

Поймай исключение и посмотри на него: catch(Exception ex)

...