2017-02-06 25 views
1

С Delphi 10 Seattle Я пытаюсь клонировать TFDQuery с TFDMemTable и сохранять изменения, внесенные в TFDMemTable, в базу данных.Могут ли изменения, внесенные в TFDMemTable, клонированные из TFDQuery, отправляться обратно в базу данных?

Изменения в памяти появляются в запросе, но не проходят весь путь до БД. Если я изменяю значения в запросе напрямую, они сохраняются в базе данных.

var 
    query : TFDQuery; 
    memtable : TFDMemTable; 
begin 
    { run TFDQuery } 
    query := TFDQuery.Create(nil); 
    query.SQL.Text := 'select * from employee'; 
    query.Open; 

    { clone query into memtable } 
    memtable := TFDMemTable.Create(nil); 
    memtable.CloneCursor(query); 

    { go to the same record in query and memtable } 
    memtable.First; 
    query.First; 
    Assert(memtable.Fields[0].Value = query.Fields[0].Value); 

    { edit the record in the memtable from ABC to XYZ } 
    Assert(memtable['SomeField'] = 'ABC'); 
    memtable.Edit; 
    memtable['SomeField'] := 'XYZ'; 
    memtable.Post; 

    { verify record also changed in query } 
    Assert(query['SomeField'] = 'XYZ'); 

    { has the change gone through to the database? } 
    query.Close; 
    query.Open; 
    query.First; 
    Assert(query['SomeField'] = 'XYZ'); // assertion fails, value is still ABC 
+0

В ApplyUpdates на TFDQuery должен делать свою работу. Можете ли вы поделиться кодом, когда вы его попробовали? –

+0

Я думаю, что я, должно быть, сначала вызывал его как в MemTable, так и в Query. Первый вызов означал, что записи остались неизменными, а во втором - нет записей для обновления. – LachlanG

ответ

1

Интересный q. Я сделал пустую попытку, используя MergeDataSet.

Однако, тогда я подумал, не пытаюсь ли я сделать слишком много еды. Скорее, к моему удивлению, следующие работы найти для меня, и изменения, внесенные в FDMemTable, сохраняются в базу данных (MS SQL Server 2014 с использованием таблицы авторов в MS пабы базы данных, Delphi Seattle):

procedure TForm1.btnCopyToMemTableClick(Sender: TObject); 
begin 
    FDMemTable1.CloneCursor(FDQuery1); 
end; 

procedure TForm1.btnSaveBackClick(Sender: TObject); 
var 
    Errors : Integer; 
begin 
    Errors := FDQuery1.ApplyUpdates; 
    FDQuery1.Close; 
    // need to close FDMemTable1 before re-opening FDQuery1, otherwise the 
    // call to FDQuery1 provokes a complaint about a duplicated column. 
    FDMemTable1.Close; 

    FDQuery1.Open; 
    FDMemTable1.CloneCursor(FDQuery1); 
end; 

Из-за этого, кажется, что у вашего кода не хватает query.ApplyUpdates(0) до того, как query закрыт, и необходимо позвонить memtable.close, прежде чем пытаться заново открыть query, чтобы избежать ошибки, отмеченной в коде.

Итак, в этом случае применяется KISS, но мне бы хотелось знать, есть ли способ достичь того же результата, используя MergeDataSet.

Btw, следующий незначительные изменения коды, чтобы адаптировать его к моей тестовой платформе:

var 
    query : TFDQuery; 
    memtable : TFDMemTable; 
begin 
    // Using the MS pubs demo database 
    query := FDQuery1; 
    query.SQL.Text := 'select * from authors'; 
    query.CachedUpdates := True; 
    query.Open; 

    { clone query into memtable } 
    memtable := FDMemTable1; 
    memtable.CloneCursor(query); 

    { go to the same record in query and memtable } 
    memtable.First; 
    query.First; 
    Assert(memtable.Fields[0].Value = query.Fields[0].Value); 

    { edit the record in the memtable from ABC to XYZ } 
    //Assert(memtable[''] = 'ABC'); 
    memtable.Edit; 
    memtable['Phone'] := '666'; 
    memtable.Post; 

    { verify record also changed in query } 
    Assert(query['Phone'] = '666'); 

    // Added 
    query.ApplyUpdates(0); 
    { has the change gone through to the database? } 
    query.Close; 

    // Added 
    // need to close memtable before re-opening query, otherwise the 
    // call to query provokes a complaint about a duplicated column. 
    memtable.Close; 

    query.Open; 
    query.First; 
    Assert(query['Phone'] = '666'); // assertion succeeds 
+0

Спасибо, я думаю, что то, что я делал неправильно, также вызывало приложение ApplyUpdates в MemTable, прежде чем я вызвал его в Query. Похоже, что новая запись остается неизменной, и поэтому запрос Query ApplyUpdates не считает, что запись нуждается в обновлении. – LachlanG

+0

@LachlanG: Хорошо, это звучит правдоподобно ... – MartynA