Delphi TADOQuery.next пропуская запись
Описание заявки / обработки
Я поддерживаю старый код в Delphi XE. Приложение выполняет запрос к базе данных на удаленном сервере, а затем создает отчет на ПК. У нас был отчет об ошибке, что некоторые данные в одном из полей отсутствуют. Данное поле содержит огромное количество данных (несколько тысяч символов), собранных с сервера. Я не контролирую, какие данные собираются и хранятся в этом поле. Я обнаружил, что ошибка вызывается нулевыми значениями и другими управляющими символами (переводы строк и т. Д.), Встроенными в эти данные. Когда вызывался метод SaveToFile в TADOQuery, нулевые значения и другие управляющие символы приводили к тому, что любые последующие данные в поле игнорировались (SaveToFile в основном доходил до управляющих символов и прекращал чтение записи).
Решение этой ошибки заключалось в извлечении соответствующего поля из набора результатов, отфильтровывании любых управляющих символов и сохранении его во временном файле (на данный момент я не мог поместить его обратно в набор результатов, поскольку он находился в режиме чтения. только государство). Данные сохраняются в формате XML, поэтому я также должен сделать некоторые символы удобными для XML (как вы увидите в фрагменте кода). После вызова метода SaveToFile я считывал исправленные данные из временного файла и записывал их обратно в сохраненный отчет. Это многословно, но это работает.
Эта проблема
У меня сейчас новая проблема. Я замечаю, что в некоторых случаях в конце файла будет отсутствовать одна запись (рассматриваемое поле будет пустым). Я провел целую вечность, копаясь в проблеме, и она сводится к следующему коду (который используется для извлечения данных из поля перед вызовом SaveToFile). Код пропускает одну строку. Не каждый раз - примерно один из каждых двух или трех запусков запросов. Я знаю это для факта, потому что я добавил счетчик в цикл ниже при отладке и сравнил число выполнений цикла с количеством записей, и он возвращался на единицу меньше, когда произошла ошибка (в результате пустое поле), и равны, когда все данные появились в отчете. Никаких исключений не происходит, поэтому они не падают ни на что, а буквально пропускают запись.
assignfile(f, tempFilename);
rewrite(f);
adoqry.first;
repeat
try
bytes := adoqry.fieldByName(fld).AsBytes;
tmp := '';
for i := 0 to length(bytes) - 1 do
if bytes[i] < 32 then // strip any control characters (nulls, line feeds etc.) from the string
tmp := tmp + ' '
else
begin
case char(bytes[i]) of
'&': tmp := tmp + '&';
'''': tmp := tmp + ''';
'"': tmp := tmp + '"';
'>': tmp := tmp + '>';
'<': tmp := tmp + '<';
else
tmp := tmp + char(bytes[i]);
end;
end;
// when debugging, inc counter here to prove that the loop has been executed
writeln(f, UTF8String(tmp));
setLength(bytes, 0);
except on e: exception do
writeln(f, '');
end;
adoqry.next;
until adoqry.eof;
closefile(f);
Вопрос
Есть ли какая-то причина, по которой приведенный выше код пропустил бы запись (т.е. выполнял цикл только n - 1 раз, где n - количество записей)? Есть ли что-то, из-за чего вызов adoquery.next пропускает запись?
Изменить, чтобы уточнить вопросы, поднятые в комментариях
Данные отсутствуют в отчете. Это всегда одна запись, которая не обрабатывается. У меня в отчете более 20000 записей, а недостающая запись где-то посередине, но сузить ее сложно, так как данных так много. Поскольку пропускается одна запись, все после этой записи сдвигается вверх по записи (это означает, что большая часть отчета тогда неверна), а последняя запись содержит пустое поле.
1 ответ
Кажется, я наткнулся на решение этой проблемы. Я все еще тестирую, но, похоже, сейчас все исправлено.
Прежде чем я углубился в это, я отследил пропущенную запись. Есть ряд записей с одинаковыми данными в них. Я удалил запись, которая пропускалась, чтобы увидеть, что произойдет, и обработка пропустила другую запись (которая содержала те же данные). Как и прежде, он только пропускал его периодически (один раз в каждые два или три запуска запроса).
На "исправить"...
Я подумал, что попытаюсь внести несколько изменений в настройку TADOQuery, чтобы увидеть, как это повлияет. В течение многих лет он работал нормально со следующей настроенной опцией:
adoqry.executeOptions := [eoAsyncFetch];
Я закомментировал эту строку, и вдруг обработка работает нормально. Я выполнил несколько запросов, и все они возвращаются со всеми строками. Ничего не пропускается. Я продолжу тестировать, но кажется (на данный момент) все исправлено.