'ExecuteReader требует открытого и доступного соединения.Текущее состояние соединения открыто - PullRequest
6 голосов
/ 24 октября 2011

Довольно большое веб-приложение, написанное на C #, продолжает выдавать 2 ошибки:

'ExecuteReader требует открытого и доступного соединения.Текущее состояние соединения открыто. 'и 'Недопустимая попытка вызвать Read, когда читатель закрыт.'

Эти ошибки были спорадическими - страницы, используемые для нормальной загрузки примерно 95% времени, но в последнее время они стали эндемичными, они происходятвсе время и в основном наносит вред функциональности приложения.

Веб-приложение в значительной степени зависит от базы данных MS SQL, и ошибки, по-видимому, не ограничиваются только одной страницей, а почти всеми страницами, которые подключаются кбаза данных.

Запросы выполняются следующим образом:

Database.Open(); // Custom class that has our connection string hard coded.

string query = "SELECT * FROM table"; // (dummy query)
SqlCommand command = new SqlCommand(query, Database.Conn);

SqlDataReader reader = null;

try {
    reader = command.ExecuteReader(CommandBehaviour.CloseConnection);

    if (reader.HasRows) {

        while (reader.Read()) {
            // Do something with the data.
        }
   }
    reader.Close();
}
catch (Exception e) {
    throw new Exception(e.Message);
}
finally {
    if (reader != null) {
        reader.Close();
    }
}

Я исследовал эти ошибки в Интернете и увидел несколько потенциальных решений, которые я пытался безрезультатно.:

Помещение различных частей кода в блок using ().Указание CommandBehaviour.CloseConnection для читателя.Проверка того, что MARS включен.Гарантируя, что каждый раз создается новый объект подключения.

Я потратил целую вечность на поиски решения этой проблемы, не говоря уже о долгом долгом времени, пытаясь заставить его работать, и я почти на гранипотянув меня за волосы сейчас!

Пожалуйста, помогите!

РЕДАКТИРОВАТЬ - Исправлена ​​проблема, см. раздел комментариев.

Ответы [ 2 ]

6 голосов
/ 24 октября 2011

Мне кажется, что Database - это тип, а не экземпляр.

У вас сейчас проблемы с многопоточностью.

У вас есть 2 варианта:

  • Применить [ThreadStatic] к полю, содержащему объект соединения, созданный Database.Open()

или

  • Сделать Database.Open() вернуть свежий экземпляр объекта соединения и использовать его при создании команды
4 голосов
/ 24 октября 2011

В дополнение к leppie 's answer вы также должны быть Dispose() ing любого из IDisposable типов:

        try
        {
            Database.Open(); // Custom class that has our connection string hard coded.

            string query = "SELECT * FROM table"; // (dummy query)

            using (SqlCommand command = new SqlCommand(query, Database.Conn))
            using (SqlDataReader reader = command.ExecuteReader(CommandBehaviour.CloseConnection))
            {
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        // Do something with the data.
                    }
                }
            }
        }
        catch (Exception e)
        {
            throw new Exception(e.Message);
        }
...