powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Проблема с простеньким кодом
24 сообщений из 24, страница 1 из 1
Проблема с простеньким кодом
    #39985199
Petrashkevich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте !
Есть проходная предприятия, где люди проходя прикладывают пропуск к сканеру. Сканер считывает код и запускает процедуру обработки.
Процедура делает следующее
1. Записывает поступивший код в базу (подключена локальная база на .MDB) - логирует
2. Формирует запрос на поиск сотрудника
3. Ищет сотрудника в базе. К ShowEmployee подключён TDataSource и TDBImage+TDBText. Фото и ФИО найденного сотрудника отображается на мониторе.
4. Если сотрудник найден, то он записывается в таблицу регистрации
5. И запускается процедура обработки списка регистрации таймером.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
procedure DoEnterCode(Code: string);
var Id: integer;                                    
begin
  if Code = '' then Exit;
  ShowEmployee.Close;
  while Length(Code)>0 do // удаляем ведущие ноли
    if Code[1] = '0' then Delete(Code,1,1) else Break;
  ExecSQL('insert into ALog(ANumber,ADate) select :N,:D',[Code,Now()]);  // запись в таблицу логирования
  ShowEmployee.SQL.Text := 'select * from Employee E where TabNumber = '''+Code+'''';  // формируем запрос на поиск сотрудника
  ShowEmployee.Open; // здесь сотрудник найден и показывается на экране монитора 
  if not ShowEmployee.IsEmpty then // если запрос вернул сотрудника
    ExecSQL('insert into EmployeeRegistration(IdEmployee,ADate) values(:IdEmployee,:ADate)',[ShowEmployee['IdEmployee'],Now()]); // записываем сотрудника в базу
  ShowEmployeeRegistration.Execute; // обновляем список зарегистрированных сотрудников
  Timer1.Enabled := true; // запускаем таймер на обработку списка
end;



Обработка списка происходит следующим образом1. Если есть в списке люди
2. Создаётся поток, который запускает хранимую процедуру на MSSQL и пытается записать сотрудника в базу
3. Если процедура вернула значение (возвращается ID сотрудника), то есть запись в базу произошла, то этот сотрудник из списка удаляется и таймер запускается снова.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
procedure Timer1Timer(Sender: TObject);
var Id: integer;
    A: TADOThread;
    S: string;                           
begin
  Timer1.Enabled := false;
  if not EmployeeRegistrationShow.IsEmpty then begin  // если есть люди в списке                                                                        
    A := TADOThread.Create(nil,ConnectStr); // создаётся поток
    A.OnAfterExecute := DoAfterExecute;  // здесь мы удаляем сотрудника если сервер ответил положительно
    A.OnThreadError := DoThreadError; // здесь мы гасим ошибку сервера об отсутствии связи
    S := 'exec EmployeeRegistrationChange '+IntToStr(EmployeeRegistrationShow['IdEmployee'])+','+
                IdClient+','+                                                                                                                                                                                               
                ''''+ FormatDateTime('yyyymmdd hh:mm:ss',EmployeeRegistrationShow['ADate'])+'''';        
    A.ExecQuery(S);
  end;                                       
end;



Проблема в следующем.
Приблизительно раз-два в неделю, сотрудник(разный) не попадает в базу. Количество сотрудников в день ~4000.
При этом его нет ни в таблице ALog ни в таблице EmployeeRegistration. В ALog пишется все полученные коды, а в EmployeeRegistration только найденные сотрудники
Но на экране монитора он есть! Это подтверждает камера видеонаблюдения, на которой видно и сотрудника и его фото на мониторе.
Помогите пожалуйста с идеей, как объяснить такое поведение. Или с идеей как изменить систему записи
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985204
delphinotes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Petrashkevich,

Может быть ExecSQL не делает Commit/AutoCommit? В какой момент фиксируется транзакция, до отображения карточки сотрудника, или где-то позже?
Что значит "здесь мы удаляем сотрудника если сервер ответил положительно"?
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985211
Petrashkevich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
> В какой момент фиксируется транзакция, до отображения карточки сотрудника, или где-то позже?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
// сначала пишем в ALog
ExecSQL('insert into ALog(ANumber,ADate) select :N,:D',[Code,Now()]);
// затем ищем сотрудника и отображаем его на экране
ShowEmployee.SQL.Text := 'select * from Employee E where TabNumber = '''+Code+'''';
ShowEmployee.Open; // сюда прицеплен TDatasoure + TDBImage 
// если сотрудник найден, то пишем его в EmployeeRegistration
if not ShowEmployee.IsEmpty then 
  ExecSQL('insert into EmployeeRegistration(IdEmployee,ADate) values(:IdEmployee,:ADate)',[ShowEmployee['IdEmployee'],Now()]);



>Что значит "здесь мы удаляем сотрудника если сервер ответил положительно"?
Есть 2 таблички ALog и EmployeeRegistration.
В ALog пишется всё, а в EmployeeRegistration пишутся найденные сотрудники, которые отобразились на экране и которых нужно отослать на сервер.
То есть, в EmployeeRegistration формируется список, который нужно выгрузить на сервер.
1. В таймере, перечитывается табличка EmployeeRegistration (список выгрузки).
2. Если там есть данные, то запускается поток в котором идёт попытка вызвать хранимку на Сервере.
3. Если Хранимка ответила положительно (вернула значение ID сотрудника, которого мы пытаемся выгрузить) то этот сотрудник удаляется из выгружаемого списка и запускается таймер снова - пункт №1
4. Если Хранимка не ответила (сбой в сети), то ничего не происходит, сотрудник остаётся в списке и при следующем итерации таймера его снова будут пытаться отослать на сервер.
Так таймер и крутится, пока список не пустой.

Но это всё лирика, проблема в другом. Сотрудник отображается на экране но его данных нет в ALog. А с ALog ничего не удаляется. Эта таблица введена специально для отслеживания всех поступивших кодов.
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985213
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petrashkevich,

какая то не правильная у вас бизнес-модель. Таймер зачем то приплетен...
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985216
Petrashkevich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
>какая то не правильная у вас бизнес-модель.
Пожалуйста, подскажите как правильно

>Таймер зачем то приплетен...
Таймер для итерации списка. К данной проблеме он отношения не имеет
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985222
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petrashkevich
>какая то не правильная у вас бизнес-модель.
Пожалуйста, подскажите как правильно

>Таймер зачем то приплетен...
Таймер для итерации списка. К данной проблеме он отношения не имеет

MSSQL достаточно мощный инструмент, что бы делать все там.
SQL Server Agent -> Jobs (вместо таймера)
По факту: на сервер через ХП должен передаваться код и все остальное должен делать сервере.

p.s.
автор
Код: pascal
1.
2.
3.
S := 'exec EmployeeRegistrationChange '+IntToStr(EmployeeRegistrationShow['IdEmployee'])+','+
                IdClient+','+                                                                                                                                                                                               
                ''''+ FormatDateTime('yyyymmdd hh:mm:ss',EmployeeRegistrationShow['ADate'])+'''';      


даже не знаю, как без мата охарактеризовать это, без обид
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985225
Petrashkevich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
>По факту: на сервер через ХП должен передаваться код и все остальное должен делать сервере.
Так всё и происходит.

Проблема в другом.
1. Сотрудник пишется в таблицу Логирования (локальная таблица Access)
2. Сотрудник отображается на экране (это видно на камере наблюдения)
3. Сотрудник пишется в список отправки на сервер. (локальная таблица Access)

Ни в ПЕРВОЙ ни во ВТОРОЙ таблице сотрудника нет, а на экране сотрудник ЕСТЬ!!!
И происходит это 1-2 раза в неделю. То есть за 5 дней проходит 5*4000=20 тысяч сотрудников и 1-2 куда то исчезают
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985226
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petrashkevich
>По факту: на сервер через ХП должен передаваться код и все остальное должен делать сервере.
Так всё и происходит.

Проблема в другом.
1. Сотрудник пишется в таблицу Логирования (локальная таблица Access)
2. Сотрудник отображается на экране (это видно на камере наблюдения)
3. Сотрудник пишется в список отправки на сервер. (локальная таблица Access)

Ни в ПЕРВОЙ ни во ВТОРОЙ таблице сотрудника нет, а на экране сотрудник ЕСТЬ!!!
И происходит это 1-2 раза в неделю. То есть за 50 дней проходит 5*4000=20 тысяч сотрудников и 1-2 куда то исчезают

1) Логирование должно происходить на сервере. На клиенте не должно быть
Код: pascal
1.
ExecSQL('insert into ALog(ANumber,ADate) select :N,:D',[Code,Now()]);

и т.п.
2) Наиболее вероятное поведение, описанное вами, является следствием подвисшей транзакции. Какая причина сбоя, возможно криво передаются данные.
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985233
Petrashkevich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Gerasimenko

1) Логирование должно происходить на сервере. На клиенте не должно быть
Код: pascal
1.
ExecSQL('insert into ALog(ANumber,ADate) select :N,:D',[Code,Now()]);

и т.п.

Как логироване должно происходить на сервере, если сервер недоступен ? Вот оборвалась связь, повис роутер, свет выключили, сервер не стартанул. Где всё это время хранятся данные ? Система работает без наличия сервера в сети. Сервер появился (связь восстановили) все записанные данные сбросились на сервер.

Gerasimenko

2) Наиболее вероятное поведение, описанное вами, является следствием подвисшей транзакции. Какая причина сбоя, возможно криво передаются данные.

Данных нет ни в ПЕРВОЙ (локальной) таблице ни во ВТОРОЙ (локальной) ни на сервере.
Как ГАРАНТИРОВАННО записать в таблицу ACCESSа ?
Может быть перевести СПИСОК на отправку в Фаил ? То есть не писать это список в таблицу Access, а писать напрямую в текстовый файл ? Там блокировок не будет ?
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985237
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petrashkevich
Gerasimenko

1) Логирование должно происходить на сервере. На клиенте не должно быть
Код: pascal
1.
ExecSQL('insert into ALog(ANumber,ADate) select :N,:D',[Code,Now()]);

и т.п.

Как логироване должно происходить на сервере, если сервер недоступен ? Вот оборвалась связь, повис роутер, свет выключили, сервер не стартанул. Где всё это время хранятся данные ?

Gerasimenko

2) Наиболее вероятное поведение, описанное вами, является следствием подвисшей транзакции. Какая причина сбоя, возможно криво передаются данные.

Данных нет ни в ПЕРВОЙ (локальной) таблице ни во ВТОРОЙ (локальной) ни на сервере.
Как ГАРАНТИРОВАННО записать в таблицу ACCESSа ?

1) вы противоречите себе сами. авторКак логироване должно происходить на сервере, если сервер недоступен ?
Тогда у что-то типа TStringList.SaveToFile.Да и в случае разрыва возникнет Exception
2) авторСоздаётся поток, который запускает хранимую процедуру на MSSQL и пытается записать сотрудника в базу
зачем еще какой то ACCESS и уж тем более авторСоздаётся поток
Вопросов больше чем ответов
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985238
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petrashkevich,
авторМожет быть перевести СПИСОК на отправку в Фаил ? То есть не писать это список в таблицу Access, а писать напрямую в текстовый файл ? Там блокировок не будет ?
Работайте напрямую с MSSQL.Что мешает там создать табличку со списком необработанных данных со сканера и запускать по расписанию Job
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985241
Petrashkevich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
> вы противоречите себе сами
Не виду противоречий

> Да и в случае разрыва возникнет Exception
Возникает, но гасится в событии OnThreadError, чтобы на экране не всплывало окно с ошибкой доступа. Сервер не ответил положительно, данные из таблички Регистрации не удаляются.

>зачем еще какой то ACCESS
Там хранится табличка сотрудников с их ФИО и ФОТО. Программа локальная, нужно где-то хранить данные сотрудников.

>уж тем более "Создаётся поток"
Поток нужен для того, чтобы основная программа не подвисала в ожидании ответа сервера. Если сервер не отвечает, то через таймаут приходит ошибка, которая гасится.

Смысл программы - накапливать данные и отсылать их на сервер когда тот появится в сети.
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985242
Petrashkevich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
>Работайте напрямую с MSSQL
Сервера нет в сети. Нет связи. Программа накапливает данные и отсылает их, когда связь восстанавливается
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985244
Gluck99
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Gerasimenko
2) Наиболее вероятное поведение, описанное вами, является следствием подвисшей транзакции. Какая причина сбоя, возможно криво передаются данные.
У него проблема не с MS SQL, а с Access. Вообще тут вместо тормознутого Access'a по идее достаточно простой записи в файл с разделителями. Потом для передачи на сервер формируем пакетом insert в одной транзакции. Если весь пакет ушёл нормально, то файл удаляем. Если транзакция откатилась, то файл с сотрудниками остаётся и продолжает пополняться.
С логами та же история - они пишутся локально в файл. Каждый день - новый файл. Логи можно периодически забрасывать на сервер, если надо их как-то сложно обрабатывать потом.
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985245
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petrashkevich
>Работайте напрямую с MSSQL
Сервера нет в сети. Нет связи. Программа накапливает данные и отсылает их, когда связь восстанавливается

1)С потоком все одно не понятно. MSSQL может общаться с ACCESS и наоборот.
2)хранить можно и в ACCESS и в текстовом файле. Причем во втором случае BULK INSERT очень удобен
3) Лучше на форуме по ACCESS спросить, почему откатывает. явного криминала нет
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985246
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Gluck99
Gerasimenko
2) Наиболее вероятное поведение, описанное вами, является следствием подвисшей транзакции. Какая причина сбоя, возможно криво передаются данные.
У него проблема не с MS SQL, а с Access. Вообще тут вместо тормознутого Access'a по идее достаточно простой записи в файл с разделителями. Потом для передачи на сервер формируем пакетом insert в одной транзакции. Если весь пакет ушёл нормально, то файл удаляем. Если транзакция откатилась, то файл с сотрудниками остаётся и продолжает пополняться.
С логами та же история - они пишутся локально в файл. Каждый день - новый файл. Логи можно периодически забрасывать на сервер, если надо их как-то сложно обрабатывать потом.
Да... теперь понятно
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985251
Gluck99
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petrashkevich
Сервера нет в сети. Нет связи. Программа накапливает данные и отсылает их, когда связь восстанавливается
У вас скорее всего проблема с таймером и подключением к Access. Я бы начал с проверки этой гипотезы.
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985252
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Gluck99
Petrashkevich
Сервера нет в сети. Нет связи. Программа накапливает данные и отсылает их, когда связь восстанавливается
У вас скорее всего проблема с таймером и подключением к Access. Я бы начал с проверки этой гипотезы.

1)я бы отбросил гипотезы и писал в текстовый файл
2) по доступности сервера : перекладывал файл на сервер.
3) на сервере пускай работает JOB по расписанию.
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985253
Gluck99
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Gerasimenko
2) по доступности сервера : перекладывал файл на сервер.
Это вообще лучше всего.
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985256
Фотография Кроик Семён
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petrashkevich,


мысль 1

У меня такое чувство, что у вас время от времени происходит Exception где то между отображением на экране и логированием. Вот до логирования и не доходит, обрываясь раньше.

мысль 2

Так же возможно, что логирование у вас в if <...> then <логирование> и вы упустили какой-то из вариантов.
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985272
Petrashkevich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
>С потоком все одно не понятно.
Потоком отсылается одна запись из списка накопленных. Почему потоком, чтобы не подвисала основная программа

>хранить можно и в ACCESS и в текстовом файле. Причем во втором случае BULK INSERT очень удобен
Советуете переделать хранение списка в текст ?

>Лучше на форуме по ACCESS спросить, почему откатывает. явного криминала нет
Как в Delphi отследить что запись всё таки вставлена и как её ГАРАНТИРОВАННО записать ?

>У вас скорее всего проблема с таймером и подключением к Access. Я бы начал с проверки этой гипотезы.
Как это можно проверить ?

>У меня такое чувство, что у вас время от времени происходит Exception где то между отображением на экране и логированием. Вот до логирования и не доходит, обрываясь раньше.
Сначала Логирование(запись в одну таблицу), потом Отображение (чтение из той же базы с другой таблицы), потом вторая запись в другую таблицу. Итого три операции с базой над тремя таблицами. Первая и Третья операции мимо, а средняя работает.

>Так же возможно, что логирование у вас в if <...> then <логирование> и вы упустили какой-то из вариантов.
У меня первое логирование без всяких условий (запись в ALog). Вторая запись уже по условию, если человек найден
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985308
Gluck99
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petrashkevich
Как это можно проверить ?
Надо чаще использовать try/except/finally. Вам нужно обернуть код вставки записей в БД аксеса в блоки обработки ошибок. Тогда по ошибке либо показывать сообщение, либо писать лог в текстовый файл с сообщением об ошибке и ID сотрудника, на котором произошел сбой. Кстати, это позволит вообще отказаться от таймера.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
 try
    ExecSQL('insert into ALog(ANumber,ADate) select :N,:D',[Code,Now()]);  // запись в таблицу логирования
 except
      { Тут обрабатываем возможную ошибку }
 end;

    ShowEmployee.SQL.Text := 'select * from Employee E where TabNumber = '''+Code+'''';  // формируем запрос на поиск сотрудника
    ShowEmployee.Open; // здесь сотрудник найден и показывается на экране монитора

try 
    if not ShowEmployee.IsEmpty then // если запрос вернул сотрудника
      ExecSQL('insert into EmployeeRegistration(IdEmployee,ADate) values(:IdEmployee,:ADate)',[ShowEmployee['IdEmployee'],Now()]); // записываем сотрудника в базу
except
    { Тут обрабатываем возможную ошибку }
end;

Как использовать эти операторы посмотрите в справке - там всё исчерпывающе написано.
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985322
Petrashkevich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
>Gluck99
Спасибо за идею обернуть в try/except и логировать в файл ошибку.
Попробую.
Конечно сомневаюсь, поскольку ExecSQL не глотает ошибки и они вываливались бы на экран. Но попытка- не пытка.
...
Рейтинг: 0 / 0
Проблема с простеньким кодом
    #39985488
AltHasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petrashkevich,

Как вариант использовать FB Embedded - мы используем ее в связке с Fib+, еще после вставки записи - можно проверить на успешное выполнение команды вставки. Вообще ЖарПтица практически неубиваемая вещь! ИМХО.
...
Рейтинг: 0 / 0
24 сообщений из 24, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Проблема с простеньким кодом
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]