2013-08-28 7 views
2

Я пытаюсь сохранить две таблицы с отношениями master-detail в MySQL 5.6, используя Delphi XE3 и Zeos 7.0.4. Когда я делаю ApplyUpdates на главном, поле auto increment остается равным 0. Мне нужно значение auto increment, поэтому я могу связать таблицу подробностей с полем ID главной таблицы, поступающим из ApplyUpdates. Я использую ZConnection с AutoCommit = FALSE и TransactionIsolationLevel = tiReadCommitted, ZQuery с CachedUpdates = TRUE. Что мне не хватает?Как сохранить таблицы с отношениями между деталями и деталями в рамках одной транзакции?

ZQPerson.Append; 
ZQEmployee.Append; 
try 
    ZQPersonName.Value := Edit1.Text; 
    ZQPerson.ApplyUpdates; //Here I expected to have the auto increment value on the Id field of ZQPerson, but it returns always 0 
    ZQEmployeePersonID.Value := ZQPersonId.Value; //Here I'd link Employee to it's Person record 
    ZQEmployeeRegNo.Value := StrToInt(Edit2.Text); 
    ZQEmployee.ApplyUpdates; 
    ZConnection1.Commit; //Here I would persist both tables in a single transaction to avoid master table without details 
except 
    ZQPerson.CancelUpdates; 
    ZQEmployee.CancelUpdates; 
    ZConnection1.Rollback; //In case of exceptions rollback everything 
    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') --> This is just after 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`) --> This is just after ZQEmployee.ApplyUpdates 
2013-08-29 00:02:05 cat: Execute, proto: mysql-5, msg: Native Rollback call --> Rollback after Exception on the ZQEmployee.ApplyUpdates 

ответ

0

обходной я нашел этот. Это не удовлетворяет меня полностью, потому что это не делает прозрачным использование функции автоматического увеличения базы данных, заставляя меня использовать функцию Last_Insert_ID(). Я общаюсь с разработчиками zeos, чтобы проверить это.

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; // Here I expected to have the auto increment value on the Id field of ZQPerson, but it returns always 0 
    LastID := LastInsertID('Person'); //Getting the Last_Insert_ID(), even on the uncommitted transction, works 
    ZQEmployeePersonId.Value := LastID; //Link the two tables using the Last_Insert_ID() result 
    ZQEmployeeRegNo.Value := StrToInt(Edit2.Text); 
    ZQEmployee.ApplyUpdates; 
    ZConnection1.Commit; // Here I persist both tables in a single transaction to avoid master table without details 
    except 
    ZQPerson.CancelUpdates; 
    ZQEmployee.CancelUpdates; 
    ZConnection1.Rollback; // In case of exceptions rollback everything 
    raise; 
    end; 
    ZQPerson.CommitUpdates; 
    ZQEmployee.CommitUpdates; 
2

Вы начинаете сделку с ZConnection1.StartTransaction? Я тоже думаю, что вы должны обновить ZQuery1 после вызова ZQuery1.ApplyUpdates, чтобы получить новый идентификатор.

Чтение вашего комментария, вы должны делать выбор * без предложения where? правильно? Я могу рекомендовать использовать этот подход:

1) выбрать и приращение текущего значения автоинкрементного
2) выбрать из главной таблицы, где ID = [step1 идентификатор] // это будет пустой, конечно
3) добавить деталь используя идентификатор в шаге 1
4) назначить идентификатор в главном наборе данных
5) применяются оба обновления

+0

Проблема заключается в том, что Refresh укажет на первую запись в наборе данных и не вернет следующее значение автоматического увеличения. –

+0

Как выбрать текущее значение автоматического увеличения, чтобы выполнить шаг 1? –

+0

Я использую Select * из продукта для ZQProduct и Select * из категории продукта, где category.ProductId = product.Id для ZQCategory это просто, чтобы проверить мастер-деталь отношений, а не делать взаимосвязи правильный путь , –