TFDQuery не удается обновить? - PullRequest
0 голосов
/ 16 марта 2020

У меня проблема с синхронизацией ... У меня есть исходная таблица (mtAllowanceCategory), которую я хочу обновить до ее копии (qryAllowanceCategory). Чтобы убедиться, что записи в копии удалены, если они больше не присутствуют в источнике, копия имеет логическое поле «StillHere», которое устанавливается на, когда запись добавляется или обновляется, и в противном случае остается отключенным. После этого все записи с StillHere = false удаляются.

Такова идея, во всяком случае ... на практике поля флага не включаются при публикации обновлений. Когда я отслеживаю код, оператор выполняется; когда я смотрю в Access, он остается выключенным. Следовательно, delete SQL впоследствии очищает всю таблицу.

пытался понять это часами; что мне не хватает ??

mtAllowanceCategory:TFDMemTable (filled from an API call, this works fine)
qryAllowanceCategory:TFDQuery
conn:TFDConnection to a local Access database (also used for qryAllowanceCategory)

  conn.ExecSQL('UPDATE AllowanceCategory SET StillHere=false;');

  while not mtAllowanceCategory.eof do
  begin
    if qryAllowanceCategory.locate('WLPid',mtAllowanceCategory.FieldByName('Id').AsString,[loCaseInsensitive]) then
    begin
      Updating:=true;
      qryAllowanceCategory.Edit;
    end
    else
    begin
      Updating:=false;
      qryAllowanceCategory.Insert;
    end;
    qryAllowanceCategory.fieldbyname('createdBy').AsString:=mtAllowanceCategory.FieldByName('createdBy').AsString;
    qryAllowanceCategory.fieldbyname('createdOn').AsString:=mtAllowanceCategory.FieldByName('createdOn').AsString;
    qryAllowanceCategory.fieldbyname('description').AsString:=mtAllowanceCategory.FieldByName('description').AsString;
    qryAllowanceCategory.fieldbyname('WLPid').AsString:=mtAllowanceCategory.FieldByName('id').AsString;
    qryAllowanceCategory.fieldbyname('isDeleted').Asboolean:=mtAllowanceCategory.FieldByName('isDeleted').Asboolean;
    qryAllowanceCategory.fieldbyname('isInUse').Asboolean:=mtAllowanceCategory.FieldByName('isInUse').Asboolean;
    qryAllowanceCategory.fieldbyname('modifiedBy').AsString:=mtAllowanceCategory.FieldByName('modifiedBy').AsString;
    qryAllowanceCategory.fieldbyname('modifiedOn').AsString:=mtAllowanceCategory.FieldByName('modifiedOn').AsString;
    qryAllowanceCategory.fieldbyname('WLPname').AsString:=mtAllowanceCategory.FieldByName('name').AsString;
    qryAllowanceCategory.fieldbyname('number').AsInteger:=mtAllowanceCategory.FieldByName('number').AsInteger;
    qryAllowanceCategory.fieldbyname('percentage').AsFloat:=mtAllowanceCategory.FieldByName('number').AsFloat;
    qryAllowanceCategory.fieldbyname('remark').AsString:=mtAllowanceCategory.FieldByName('remark').AsString;
    qryAllowanceCategory.fieldbyname('LocalEdited').AsBoolean:=false;
    qryAllowanceCategory.fieldbyname('LocalInserted').AsBoolean:=false;
    qryAllowanceCategory.fieldbyname('LocalDeleted').AsBoolean:=false;
    qryAllowanceCategory.fieldbyname('StillHere').AsBoolean:=true;
    qryAllowanceCategory.Post;
    mtAllowanceCategory.next;
  end;
  conn.commit;
  conn.ExecSQL('DELETE FROM AllowanceCategory WHERE StillHere=false;');

Ответы [ 2 ]

1 голос
/ 22 марта 2020

Когда я читал ваш вопрос, меня поразили две мысли:

Одна заключалась в том, что я не мог сразу увидеть причину вашей проблемы, а другая - в том, что вы, возможно, все равно могли избежать этой проблемы, если бы использовали Sql, а не обход таблиц в коде.

Мне показалось, что вы можете сделать большинство, если не все, что вам нужно, с точки зрения синхронизации двух таблиц, используя Access Sql вместо обхода таблицы qryAllowanceCategory с помощью while not EOF л oop. (кстати, в дальнейшем я буду использовать 'mtA C' и qryA C, чтобы уменьшить количество набираемых символов и опечаток)

Использование Access SQL

Изначально мне не очень повезло, так как Access отклонил мои попытки ссылаться на обе таблицы в операторе Update против qryA C с использованием Join или Outer Join, но затем я наткнулся на ссылку, которая показала, что Access поддерживает синтаксис внутреннего соединения. Эти операторы SQL успешно выполняются путем вызова ExecSQL в соединении FireDA C с базой данных:

update qryAC set qryAC.StillHere = True 
  where exists(select mtAC.* from mtAC inner join qryAC on mtAC.WLPid = qryAC.WLPid)

и

update qryAC inner join mtAC on mtAC.WLPid = qryAC.WLPid set qryAC.AValue = mtAC.AValue

Этот первый из них, очевидно, обеспечивает способ обновить поле StillHere, установив для него значение True или False с тривиальной модификацией.

Второе показывает способ обновления набора полей в qryA C из соответствующих строк в mtAC, и это может конечно, ограничиться подмножеством строк с подходящим предложением Where.

Access Sql также поддерживает проверку, существует ли строка в одной таблице в другой, как в

select * from qryAC q where exists (select * from mtac m where q.wlpid = m.wlpid)

и для удаления строк в одной таблице, которые не существуют в другой

delete from qryAC q where not exists (select * from mtac m where q.wlpid = m.wlpid)

Использование FireDA C Local SQL

Я также упомянул LocalSQL в комментарии. Это поддерживает гораздо более широкий диапазон операторов Sql, которые являются родными Access Sql и могут работать с любым потомком TDataSet, поэтому, если вы обнаружите что-то, что синтаксис Access Sql не поддерживает, это стоит рассматривая использование Local SQL вместо этого. Его основным недостатком является то, что он работает с наборами данных с использованием обходов, поэтому он не такой «мгновенный», как нативный Sql. Это может быть немного сложно настроить, так что вот настройки DFM, которые показывают, как компоненты должны подключаться. Вы можете использовать его, передавая то, что вы хотите, в FDQuery1.

объект AccessConnection: TFDConnection Params.Strings = ('База данных = D: \ Delphi \ Code \ FireDAC \ LocalSQL \ Allowance.accdb' 'DriverID = MSA cc ') Connected = True LoginPrompt = False end

объект mtA C: TFDQuery AfterOpen = mtACAfterOpen Connection = AccessConnection SQL .Strings = (' select * from mtA C ') end

объект qryA C: соединение TFDQuery = конец AccessConnection

объект LocalSqlConnection: TFDConnection Params.Strings = ('DriverID = SQLite') Connected = True LoginPrompt = False end

объект FDLocalSQL1: TFDLocalSQL Connection = LocalSqlConnection DataSets = ​​end

объект FDGUIxWaitCursor1: TFDGUIxWaitCursor Provider = конечный объект 5-го уровня данных *

объект FDQuery1: TFDQuery Connection = LocalSqlConnection end

0 голосов
/ 20 марта 2020

Если кому-то интересно: проблема в том, что не удалось обновить qryAllowanceCategory после первоначальной SQL, установив StillHere в false. Версия памяти (qryAllowanceCategory) записи не получила это обновление, поэтому, по его словам, флаг все еще был включен; после появления обновлений полей изменений не было (все остальные поля также не изменились), поэтому сообщение было проигнорировано. В реальной таблице он был отключен, поэтому окончательное удаление SQL удалило его.

Проблема была решена путем добавления refre sh после первого оператора UPDATE SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...