У меня есть блок кода, предназначенный для извлечения текстовых описаний из таблицы базы данных и сохранения их в текстовый файл. Это выглядит так (C# .NET):
OdbcCommand getItemsCommand = new OdbcCommand("SELECT ID FROM ITEMS", databaseConnection);
OdbcDataReader getItemsReader = getItemsCommand.ExecuteReader();
OdbcCommand getDescriptionCommand = new OdbcCommand("SELECT ITEMDESCRIPTION FROM ITEMS WHERE ID = ?", databaseConnection);
getDescriptionCommand.Prepare();
while (getItemsReader.Read())
{
long id = getItemsReader.GetInt64(0);
String outputPath = "c:\\text\\" + id + ".txt";
if (!File.Exists(outputPath))
{
getDescriptionCommand.Parameters.Clear();
getDescriptionCommand.Parameters.AddWithValue("id", id);
String description = (String)getDescriptionCommand.ExecuteScalar();
StreamWriter outputWriter = new StreamWriter(outputPath);
outputWriter.Write(description);
outputWriter.Close();
}
}
getItemsReader.Close();
Этот код успешно сохранил часть данных в файлах .txt, но для многих строк в следующей строке создается исключение AccessViolationException:
String description = (String)getDescriptionCommand.ExecuteScalar();
Текст исключения: «Попытка чтения или записи в защищенную память. Это часто указывает на то, что другая память повреждена».
Программа обычно генерирует исключение в одних и тех же строках таблицы, но это не выглядит на 100% согласованным. Иногда данные, которые вызывали исключение в прошлом, внезапно срабатывают.
Некоторые люди, несомненно, задаются вопросом, почему я не просто ВЫБРАЛ ИДЕНТИФИКАТОР, ОПИСАНИЕ ИЗДЕЛИЯ ИЗ ПУНКТОВ в getItemsCommand и пропустил второй запрос. Собственно, изначально я так и поступил, и я столкнулся с той же ошибкой с getItemsCommand.GetString (). Я боялся, что, возможно, набор данных занимал слишком много памяти и, возможно, это было причиной ошибки. Поэтому я решил попробовать этот метод, чтобы посмотреть, поможет ли он. Это не так. Кто-нибудь знает, почему это может происходить?
Кстати, ID - это INT, а ITEMDESCRIPTION - это столбец VARCHAR (32000). Если это имеет значение, база данных - это Borland Interbase 6.0 (черт возьми!)
Обновлено: Я указал неправильную строку при описании того, где было выброшено исключение !! АРГХ !! Исправлено сейчас. Кроме того, я пробовал то, что предлагалось до сих пор, но они не помогли. Однако я обнаружил, что эту ошибку вызывали только очень старые записи в базе данных, что странно. Если я изменю запрос на извлечение только записей, вставленных за последние 5 лет, проблем не будет. Кто-то предположил, что это может быть проблема с преобразованием кодировки или что-то в этом роде?
Обновлять: Решил. Проблема оказалась в драйвере ODBC для нашей не очень надежной программы для работы с базами данных. Обходной путь с другими драйверами устранил проблему.





Здесь выстрел в темноте ...
Попробуйте запустить программу чтения, сохраните результат (возможно, в массиве или списке) и убедитесь, что программа чтения закрыта перед выполнением или подготовкой следующей команды. Вы даже можете пойти на крайние меры и поместить свою конструкцию getItemsCommand в блок using, чтобы вы знали, что у него нет открытых ресурсов, прежде чем выполнять следующую команду ...
Это может быть ошибка используемого вами драйвера ODBC. Какой это драйвер? Какая у вас строка подключения?
Это драйвер ODBC Easysoft Interbase. Он настроен как системный DSN с именем «BVDATA2». Строка подключения в .NET - это просто «DSN = BVDATA2».
Действительно, похоже, что это ошибка драйвера ODBC.
Да ... Услышав, что закрытие ридера не помогло, я бы определенно попытался заручиться поддержкой продавца по этому поводу ...