При работе с базами данных в режиме транзакций важно, чтобы все изменения в связанных таблицах были применены корректно. Проблема, с которой столкнулся пользователь, заключается в том, что при использовании компонентов Zeos 7.0.4 в среде Delphi XE3 для сохранения данных в таблицы с мастера-детали связью, автоинкрементное поле в таблице мастера не заполняется значением, которое необходимо для установки связи с детальной таблицей.
Оригинальный код пользователя:
ZQPerson.Append;
ZQEmployee.Append;
try
ZQPersonName.Value := Edit1.Text;
ZQPerson.ApplyUpdates; // Здесь ожидалось получить автоинкрементное значение, но возвращается 0
ZQEmployeePersonID.Value := ZQPersonId.Value; // Ссылка на запись мастера
ZQEmployeeRegNo.Value := StrToInt(Edit2.Text);
ZQEmployee.ApplyUpdates;
ZConnection1.Commit; // Зафиксировать обе таблицы в одной транзакции
except
ZQPerson.CancelUpdates;
ZQEmployee.CancelUpdates;
ZConnection1.Rollback; // При исключениях откатить все изменения
raise;
end;
ZQPerson.CommitUpdates;
ZQEmployee.CommitUpdates;
Запись из ZSQLMonitor:
2013-08-29 00:01:23 cat: Execute, proto: mysql-5, msg: INSERT INTO person (Id, name) VALUES (NULL, 'Edit1') --> Это после ZQPerson.ApplyUpdates
2013-08-29 00:01:50 cat: Execute, proto: mysql-5, msg: INSERT INTO employee (Id, RegNo, ProductId) VALUES (NULL, 1000, 0), errcode: 1452, error: Cannot add or update a child row: a foreign key constraint fails (`test`.`employee`, CONSTRAINT `FK_A6085E0491BDF8EE` FOREIGN KEY (`PersonId`) REFERENCES `person` (`Id`) --> Это после ZQEmployee.ApplyUpdates
2013-08-29 00:02:05 cat: Execute, proto: mysql-5, msg: Native Rollback call --> Откат после исключения на ZQEmployee.ApplyUpdates
Решение проблемы:
Пользователь нашел обходной путь, который заключается в использовании функции Last_Insert_ID() для получения последнего автоинкрементного значения, даже если транзакция еще не подтверждена.
function LastInsertID(ATableName: string): Integer;
var DBQuery: TZQuery;
begin
DBQuery := TZQuery.Create(Self);
with DBQuery do
begin
Connection := ZConnection1;
SQL.Clear;
SQL.Add('Select Last_Insert_ID() as Last_Insert_ID from ' + ATableName);
Open;
Result := FieldByName('Last_Insert_ID').Value;
Free;
end;
end;
procedure Persist;
var LastID: Integer;
begin
ZQPerson.Append;
ZQEmployee.Append;
try
ZQPersonName.Value := Edit1.Text;
ZQPerson.ApplyUpdates; // Здесь ожидалось автоинкрементное значение
LastID := LastInsertID('Person'); // Получение последнего автоинкрементного значения
ZQEmployeePersonID.Value := LastID; // Установка связи с записью мастера
ZQEmployeeRegNo.Value := StrToInt(Edit2.Text);
ZQEmployee.ApplyUpdates;
ZConnection1.Commit; // Фиксация транзакции
except
ZQPerson.CancelUpdates;
ZQEmployee.CancelUpdates;
ZConnection1.Rollback; // Откат транзакции при исключениях
raise;
end;
ZQPerson.CommitUpdates;
ZQEmployee.CommitUpdates;
end;
Альтернативный подход:
Для начала транзакции необходимо использовать метод StartTransaction компонента ZConnection. После применения обновлений к мастеру, необходимо обновить данные в ZQuery, чтобы получить новое автоинкрементное значение.
ZConnection1.StartTransaction;
ZQPerson.ApplyUpdates; // Применение обновлений к мастеру
ZQPerson.Refresh; // Обновление данных в ZQuery
ZQEmployeePersonID.Value := ZQPersonId.Value; // Получение автоинкрементного значения из поля Id
// Продолжение работы с детальной таблицей...
ZConnection1.Commit; // Фиксация транзакции
Заключение:
При работе с транзакциями важно правильно управлять состоянием транзакции и корректно обрабатывать автоинкрементные поля в базах данных. Использование функции Last_Insert_ID() или обновление данных в ZQuery после применения обновлений к мастеру позволяет решить проблему, описанную пользователем.
Проблема заключается в необходимости корректного получения и использования автоинкрементного значения в процессе работы с базами данных в Delphi XE3 в режиме транзакций для обеспечения связей между мастерами и деталями в таблицах.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.