Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
  #6  
Старый 27.11.2014, 20:27
phomm phomm вне форума
Новичок
 
Регистрация: 07.10.2013
Адрес: Тюмень
Сообщения: 50
Версия Delphi: 7/2007/XE+/FPC
Репутация: 22
По умолчанию

Это что-то вроде примитивной самопальной ОРМ, реализованной через несколько видов генераторов и построителей.
Это одна из важнейших функций в этой системе.

Принцип работы: берётся датасет некой сущности (таблицы) с полями типа ID ID_Foo ID_Bar и другими какими-нибудь. Этот датасет модифицируется так, что из его скрываются для показа системные поля (концепция в архитектуре таблиц БД), а к ссылочным полям клеются лукап-датасеты других сущностей, через менеджер, умеющий разруливать ссылочные поля этой сущности в нужные датасеты других сущностей. Менеджер по сути просто делает запрос к базе и выдаёт ссылку на закреплённый за запросом датасет.

Код:
procedure TBase.ModifyDataSet(ADataSet: TDataSet);
var
  i: Integer;
  Field: TStringField;
  FieldName: string;
  LookupEnt: TEntity;
  FldCnt: Integer;
  IsLookup: Boolean;
  BM: TBookMark;
begin
  BM := ADataSet.GetBookMark;
  ADataSet.Close;
  FldCnt := 0;
  ADataSet.Fields.Clear;
  for i := 0 to ADataSet.FieldDefs.Count - 1 do
  begin
    if not ADataSet.FieldDefs.Updated then
      ADataSet.FieldDefs.Update;
    if ADataSet.FindField(ADataSet.FieldDefs[i].Name) = nil then
      ADataSet.FieldDefs[i].CreateField(ADataSet);
// если это ссылочное поле 
    IsLookup := (Pos('ID_', ADataSet.FieldDefs[i].Name) <> 0); // дополнительные условия отрезаны
    if IsLookup then
    try
      FieldName := ADataSet.FieldDefs[i].Name;
      Delete(FieldName, 1, 3); // delete 'ID_'
      Field := TWideStringField.Create(nil);
      Field.Size := 128;
      Field.FieldName := FieldName;
      Field.FieldKind := fkLookup;
      Field.KeyFields := ADataSet.FieldDefs[i].Name;
// определим на что ссылается, у меня в проекте это Сущность/Entity
      LookupEnt := TEntity(EnumValue(EntP, FieldName, 'xe'));
// спец. менеджер выдаёт нужный датасет для данной энтити
      Field.LookupDataSet := Manager.GetData(LookupEnt);
// биндим поле которое будет источником инфы по ссылке
      FLookupField := 'Caption';
      if not Assigned(Field.LookupDataSet.FindField(FLookupField)) then
        FLookupField := 'Name';
      Field.LookupResultField := FLookupField;
      Field.DisplayWidth := MinWd + 1;
      Field.LookupKeyFields := 'ID';
      Field.DataSet := ADataSet;
    except
      raise;
    end;
// дообработка в наследниках формы
    SpecModifying(FldCnt, ADataSet.Fielddefs[i].Name, IsLookup);
// учёт "системных" полей таблицы
    if not (AnsiSameText('ID', ADataSet.FieldDefs[i].Name) or
      AnsiSameText('IsDeleted', ADataSet.FieldDefs[i].Name)) then
      Inc(FldCnt);
  end;
  ADataSet.Open;
  GotoBookMark(ADataSet, BM);
end;
Пояснять более, чем написал - не планирую, у меня типа говорящий код.

В итоге в датасете остаются просто поля, системные скрываются, а вот ссылочные не только скрываются, но ещё и датасет дополняется колонками из лукап-полей, показывающих поле Caption или Name из соответствующих датасетов сущностей Foo и Bar.

Этот приём позволяет добавлять и удалять таблицы, менять их поля, связи с другими таблицами, а код в программе, реализующий CRUD не меняется, везде по максимум сделана унификация, но с возможностью переопределния некоторых вещей в наследниках, только для каких-то более сложных задач дописывается вручную обработка. Надо заметить, что и база данных тоже строится/генерируется частично, что тоже способствует гибкости. Уже на нескольких проектах эта архитектура себя показывает вполне достойно.
И да, нет никакого визуального проектирования работы с базой из дельфи, используется только 1 компонент для связи с бд - адоконнекшн, никаких датасурсов квери филдов и прочего, всё что нужно программа сама генерит.

Последний раз редактировалось phomm, 27.11.2014 в 20:46.
Ответить с цитированием
Этот пользователь сказал Спасибо phomm за это полезное сообщение:
djmix (30.11.2014)
 


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 18:44.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025