Описание приложения/обработки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 раз, где п является количество записей)? Есть ли что-то, что вызовет вызов adoquery.next для пропуска записи?
Редактировать для разъяснения вопросов, поднятых в комментариях
отсутствуют данные отчета. Это всегда одна запись, которая не обрабатывается. У меня более 20 000 записей в отчете, а отсутствующая запись находится где-то посередине, но ее трудно сузить, так как имеется так много данных. Поскольку одна запись пропускается, все после этой записи сдвигает запись (что означает, что большая часть отчета ошибочна), причем окончательная запись содержит пустое поле.
Это не причина вашей проблемы, но вы никогда не должны использовать цикл повтора для итерации набора данных. Вместо этого используйте «while not DataSet.Eof do». Таким образом, ваш код не пойдет не так, если набор данных окажется пустым. – MartynA
Вы попробовали упростить свой код? Что-то вроде 'qry.First; а не qry.Eof do begin Writeln (f, qry.Fields [0] .AsString); qry.Next; конец; '? Если этот простейший код не воспроизводит вашу проблему, проблема в другом месте. – Abelisto
Btw, когда вы вызываете .SaveToFile, используете ли вы использование pfADTG или pfXML в качестве параметра TPersistfile? И возникает ли у вас такая же проблема, если вы используете другую? Мне кажется маловероятным, что, поскольку широко используется обычная программа, так как SaveToFile будет некорректно избегать данных, когда она записывает файл tp. – MartynA