Как скопировать поля из одного Query в другой ?

kill_zdm
Дата: 24.06.2019 16:48:29
Всем привет от самоучки любителя выносящего мозг десятилетиями )))))
И так друзья, кому не в лом, ответьте рекомендациями.
Много повидал подходов и реализаций. Где то свои пихнул )))
С годами менялось представление о тех или иных вещах....
Так вот, я все это к чему- прошу помощи!

Исходные данные:
1. Очень очень очень ленивый программист самоучка.
2. СУБД Postgre
3. Подобие софта работающего с СУБД пункта 2.
4. Не хочу классов в прямом понимании ))))))))))) как отдельных сущностей - только Query
5. Классы хочу, но лишь как базовые, для предоставления общих свойств и методов и возможно где то реалзизации интерфейсов, для дочерних (зебегая вперед, все вьюшки - фреймы и редакторы формы наследуемые, но это только для моей лени, что свойства и метода по сто раз одни и те же не мутить) -реализовано.
Забегая вперед, я да же MVVM реализовал на c#(wpf) но вот не лежит душа и все тут, порыпался порыпался, добился результатов и все... комп неделю не включал домашний )))) вернулся к Delphi.

И так в чем суть то в обще вопросов, а она в логике архитектуры, вот чего мне всегда реально не хватало, так это подобного опыта с нуля.
Что я решил.
1. DataModule , на него кидаю кучки Query (надоели мне все сложные запросы и всяческие FieldByName в последствии), ну допустим справочников. Это чисто плоские..точнее сами запросы плоские, типа Select поля from таблица.
-За чем? - Другие Query, без сложных запросов (если того не требуют, а просто связь отобразить) выполнят не сложный запрос к другим таблицам, а прилукапятся.
И тут первый вопрос, что быстрее, если таблица уже вскрыта в DataModule и сделается лукап нового Query по полю или запрос c присоединением Join, с точки зрения как нагрузки сети , так и (пусть это глупо прозвучит) отображения результата в виде грида клиенту?

2. Вьюшка (не буду заморачивать, тут вопрос не в этом о ее концепции создания) - Frame, таких фреймов может быть много, как с ними совладать я разберусь... допустим он один, допустим это справочник пользователей, у пользователя есть роль, хочу увидеть эту роль по имени - делаю лукап поле (ко вскрытому ранее в datamodule справочнику)

3. Форма редактор, наследница там чего то, где есть ряд свойств и методов ,которые могу передать от вьюшки. Кинул DataSource на форму редактор (без Query), форма редактор на показ инициируется и копирует в Query (виртуальную, созданную в run-time - поле класса, и ее физической datasource (этой формы) присваиваю DataSet в виде этой Query)
-За чем? - Ленив, хочу сказать POST и все и это работает (надоели мне все сложные запросы и всяческие ParamByName в последствии), но только если есть либо точная копия с полями либо скопировать в рантайм )))
Вопрос. Как скопировать поля из одной Query в другую без гемороя, включая Lookup?
всякие там
...
query2.CopyFields(query1)
...
или
...
with query2.FieldDefs.Count-1
....
работает если лукапов нет

нагородил следующий огород, только не смейтесь, не украшал, пробовал разные варики, какой то заработал, кидаую ))))
+
procedure TModelEdt.AssignQuery(AQuerySource: TUniQuery; ADataSourceDest: TUniDataSource);
var i: Integer; fld: TField;
begin
  self.QueryEdit := TUniQuery.Create(nil);
  self.QueryEdit.Connection := AQuerySource.Connection;
  self.QueryEdit.SQL.Text := AQuerySource.SQL.Text;
  self.QueryEdit.AddWhere('id=' + AQuerySource.FieldByName('id').AsString);
  for i := 0 to AQuerySource.Fields.Count - 1 do
  begin
    case AQuerySource.Fields[i].DataType of
      ftString:
        fld := TStringField.Create(Self);
      ftInteger:
        fld := TIntegerField.Create(Self);
    end;
    fld.Size := AQuerySource.Fields[i].Size;
    if AQuerySource.Fields[i].FieldKind = fkLookup then
    begin
      fld.FieldKind := fkLookup;
      fld.LookupResultField := AQuerySource.Fields[i].LookupResultField;
      fld.KeyFields := AQuerySource.Fields[i].KeyFields;
      fld.Lookup := true;
      fld.LookupKeyFields := AQuerySource.Fields[i].LookupKeyFields;
      fld.LookupDataSet := AQuerySource.Fields[i].LookupDataSet;
    end;
    fld.FieldName := AQuerySource.Fields[i].FieldName;
    fld.DisplayLabel := AQuerySource.Fields[i].DisplayLabel;
    fld.name := AQuerySource.Fields[i].name + 'Edt';
    fld.DataSet := self.QueryEdit;
  end;
  self.QueryEdit.FieldDefs.UpDate;
  ADataSourceDest.DataSet:= self.QueryEdit;



Может есть какой простой способ ?
kill_zdm
Дата: 24.06.2019 16:52:46
kill_zdm,

ну и тут я только TStringField и TIntegerField обработал, так их понятно больше, вот это и ломает )))
Gator
Дата: 24.06.2019 17:07:17
kill_zdm,

+ Нихера не понял и глаза сломал. Зато отфарматировал

procedure TModelEdt.AssignQuery(AQuerySource: TUniQuery; ADataSourceDest: TUniDataSource);
var i: Integer; fld: TField;
begin
  self.QueryEdit := TUniQuery.Create(nil);
  self.QueryEdit.Connection := AQuerySource.Connection;
  self.QueryEdit.SQL.Text := AQuerySource.SQL.Text;
  self.QueryEdit.AddWhere('id=' + AQuerySource.FieldByName('id').AsString);
  for i := 0 to AQuerySource.Fields.Count - 1 do begin
    case AQuerySource.Fields[i].DataType of
      ftString:   fld := TStringField.Create(Self);
      ftInteger: fld := TIntegerField.Create(Self);
    end;
   fld.Size := AQuerySource.Fields[i].Size;
   if AQuerySource.Fields[i].FieldKind = fkLookup then begin
     fld.FieldKind := fkLookup;
     fld.LookupResultField := AQuerySource.Fields[i].LookupResultField;
     fld.KeyFields := AQuerySource.Fields[i].KeyFields;
     fld.Lookup := true;
     fld.LookupKeyFields := AQuerySource.Fields[i].LookupKeyFields;
     fld.LookupDataSet := AQuerySource.Fields[i].LookupDataSet;
    end;
    fld.FieldName := AQuerySource.Fields[i].FieldName;
    fld.DisplayLabel := AQuerySource.Fields[i].DisplayLabel;
    fld.name := AQuerySource.Fields[i].name + 'Edt';
    fld.DataSet := self.QueryEdit;
  end;
  self.QueryEdit.FieldDefs.UpDate;
  ADataSourceDest.DataSet:= self.QueryEdit;

delphinotes
Дата: 24.06.2019 17:11:35
kill_zdm,

1. локальный лукап vs северный - всё зависит от...
можно делать и так, и так
в многопользовательской среде наверное лучше серверный, чтобы не обновлять локальные справочники постоянно

3. по сути нужен клон исходного НД (без данных, либо только для редактируемой записи) - там должен быть метод на подобии Clone
edruzenko
Дата: 24.06.2019 19:02:41
kill_zdm,


kill_zdm
что быстрее, если таблица уже вскрыта в DataModule и сделается лукап нового Query по полю или запрос c присоединением Join, с точки зрения как нагрузки сети , так и (пусть это глупо прозвучит) отображения результата в виде грида клиенту?

разумеется join быстрее на порядки.
kill_zdm
Дата: 25.06.2019 10:09:44
edruzenko,

Вы абсолютно в этом уверены? Извините, что спрашиваю, лично не проверял, мне нужно мнение - кто реально исследовал. Вот смотрите, допустим мне необходимо получить данные из связанных таблиц в кол-ве 10+ , т.е. 10+ Join, тут и запрос громоздкий ну это ладно и к СУБД напряг + нагрузка на сеть, а если уже вскрыты данные из этих таблиц, которые будут лукапиться и они в ОЗУ живут, разве это не быстрее произойдет ?
Я просто рассуждаю, не уверен абсолютно ))
kill_zdm
Дата: 25.06.2019 10:10:06
Gator,

спасибо большое, виноват, исправлюсь
kill_zdm
Дата: 25.06.2019 10:19:14
delphinotes
kill_zdm,

1. локальный лукап vs северный - всё зависит от...
можно делать и так, и так
в многопользовательской среде наверное лучше серверный, чтобы не обновлять локальные справочники постоянно

3. по сути нужен клон исходного НД (без данных, либо только для редактируемой записи) - там должен быть метод на подобии Clone


1. Конечно серверный менее геморойный я понимаю, с другой стороны при тех же равных, нагрузка возрастает сильно при многопользовтаельской , когда один и тот же справочник к примеру дергается по 100++++ раз , только что бы отобразить связанное с ним имя к примеру по ключу. Как показала практика, справочники в целом меняются не часто, часть из них в обще единожды с начальным заполнением, тут как мне видится необходимо только грамотную валидацию на существующие проверять - ну и волшебную кнопку - обновить данные добавить )))
3 - должен быть но не нашел ((((
повторюсь , я все облазил, кучу всего перепробовал, все копируется кроме лукап полей ((( сдался и начал писать свой огород, может кто реально сталкивался и знает как тот метод зовется )))
KreatorXXI
Дата: 25.06.2019 11:11:15
kill_zdm,

тащить данные с сервера на клиент (хотя бы только справочники) заранее, не разбираясь нужны они там или нет - это какая-то, действительно, специфическая концепция. Верю, что в каких-то сценариях можно сильно выиграть в быстродействии. Но гемора поиметь можно ещё больше. Особенно с валидностью данных. Вам, что жалко трафика в локальной сети?
roschinspb
Дата: 25.06.2019 11:44:28
KreatorXXI
kill_zdm,

тащить данные с сервера на клиент (хотя бы только справочники) заранее, не разбираясь нужны они там или нет - это какая-то, действительно, специфическая концепция. Верю, что в каких-то сценариях можно сильно выиграть в быстродействии. Но гемора поиметь можно ещё больше. Особенно с валидностью данных. Вам, что жалко трафика в локальной сети?
Справочники, они на то и справочники, что меняются достаточно редко (например список биологических полов). Поэтому нормальный подход это загрузить их всех в момент загрузки приложения (или при первом обращении) а затем не гонять по сети одни и те же строковые данные и не переусложнять запросы лишними join-ами. Но это конечно требует некоторой дисциплины. Гораздо проще накопипастить кучу однотипных квериков, тем более на тестовой БД данных мало и пользователь один поэтому не имеет значение сколько нам данных перекачивается. А то, что у 100 пользователей приложение едва ворочается, так это проблемы индейце шерифа не волнуют.