Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Почему в Delphi 12.3 код с SQL-запросом в FormCreate перестал работать и как это исправить

Delphi , Базы данных , SQL

 

Введение

В недавнем обсуждении на форуме разработчиков Delphi поднимался интересный вопрос: почему код, который годами работал в обработчике FormCreate, перестал корректно функционировать в Delphi 12.3 Athens. В этой статье мы разберём причины этой проблемы, предложим несколько решений и рассмотрим лучшие практики работы с формами и SQL-запросами в Delphi.

Описание проблемы

Исходный код выглядел следующим образом:

procedure TStatsGridForm.FormCreate(Sender: TObject);
begin
  Caption := sTitle + ' - Total records..' + IntToStr(iQty);
  JobTickets.SessionName := dmC.DBC1.SessionName;
  JobTickets.SQL.Clear;
  JobTickets.SQL.Add(sQuery);
  JobTickets.Prepare;
  JobTickets.Open;
end;

При этом форма создавалась и параметры задавались так:

var StatsGridForm := TStatsGridForm.create(nil);
StatsGridForm.sFileName := 'JTsInRaised';
StatsGridForm.sTitle := 'Job Tickets In/Raised..';
StatsGridForm.sQuery := Format('''Select JobNo...''',[...]);
StatsGridForm.iQty := edtTotalIn.AsInteger;

Проблема в том, что в Delphi 12.3 обработчик FormCreate вызывается сразу при создании формы (вызове конструктора Create), до того как будут установлены свойства sQuery, sTitle и iQty.

Почему это работало раньше?

Это действительно интересный вопрос. Как отмечали участники обсуждения, такой код в принципе не должен был работать, так как свойства устанавливаются после создания формы, а FormCreate вызывается в процессе создания. Возможные объяснения:

  1. В предыдущих версиях Delphi мог быть другой порядок инициализации
  2. Возможно, использовался флаг OldCreateOrder, который меняет порядок событий
  3. В коде мог быть переопределён конструктор или использованы методы BeforeConstruction/AfterConstruction

Решения проблемы

1. Перенос кода в FormShow (простое решение)

Самый простой вариант - перенести код из FormCreate в FormShow:

procedure TStatsGridForm.FormShow(Sender: TObject);
begin
  Caption := sTitle + ' - Total records..' + IntToStr(iQty);
  JobTickets.SQL.Clear;
  JobTickets.SQL.Add(sQuery);
  JobTickets.Prepare;
  JobTickets.Open;
end;

Плюсы: - Минимальные изменения кода - Гарантированно выполняется после установки всех свойств

Минусы: - Может вызываться несколько раз (если форма скрывается и показывается) - Не совсем логичное место для инициализации данных

2. Использование пользовательского конструктора (рекомендуемое решение)

Более правильный подход - создать специальный конструктор:

type
  TStatsGridForm = class(TForm)
  public
    constructor CreateWithParams(AOwner: TComponent; AQty: Integer; 
      AFileName, AQuery, ATitle: string); reintroduce;
  end;

implementation

constructor TStatsGridForm.CreateWithParams(AOwner: TComponent; AQty: Integer;
  AFileName, AQuery, ATitle: string);
begin
  inherited Create(AOwner);

  FiQty := AQty;
  FsFileName := AFileName;
  FsQuery := AQuery;
  FsTitle := ATitle;

  Caption := FsTitle + ' - Total records..' + IntToStr(FiQty);
  JobTickets.SQL.Text := FsQuery;
  JobTickets.Prepare;
  JobTickets.Open;
end;

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

var StatsGridForm := TStatsGridForm.CreateWithParams(nil, edtTotalIn.AsInteger,
  'JTsInRaised', Format('Select...', [...]), 'Job Tickets In/Raised..');

Плюсы: - Чёткий контроль порядка инициализации - Все параметры задаются в одном месте - Более безопасный и предсказуемый код

Минусы: - Требует больше изменений в существующем коде

3. Использование параметризованных запросов (лучшая практика)

Как отметил один из участников обсуждения, лучше использовать параметризованные запросы:

procedure TStatsGridForm.FormCreate(Sender: TObject);
begin
  JobTickets.SQL.Text := 'SELECT ... WHERE BusCode = :BusCode AND DateIn BETWEEN :StartDate AND :FinishDate';
  JobTickets.ParamByName('BusCode').AsString := AUD.BusCode;
  JobTickets.ParamByName('StartDate').AsDate := edtStartDate.AsDate;
  JobTickets.ParamByName('FinishDate').AsDate := edtFinishDate.AsDate;
  JobTickets.Prepare;
  JobTickets.Open;
end;

Преимущества: - Безопасность от SQL-инъекций - Более чистый код - Автоматическое экранирование и форматирование параметров

Дополнительные рекомендации

  1. Проверка активности запроса: Убедитесь, что в дизайнере запрос не активен (как советовал Uwe Raabe)

  2. Использование AfterConstruction: Если нужно сохранить текущую архитектуру, можно использовать метод AfterConstruction:

procedure TStatsGridForm.AfterConstruction;
begin
  inherited;
  if not (csDesigning in ComponentState) then
  begin
    Caption := sTitle + ' - Total records..' + IntToStr(iQty);
    JobTickets.SQL.Text := sQuery;
    JobTickets.Prepare;
    JobTickets.Open;
  end;
end;
  1. Сеттеры свойств: Можно использовать сеттеры свойств для автоматического обновления:
property sQuery: string read FsQuery write SetQuery;

procedure TStatsGridForm.SetQuery(const Value: string);
begin
  FsQuery := Value;
  if not (csDesigning in ComponentState) and (Value <> '') then
  begin
    JobTickets.SQL.Text := Value;
    JobTickets.Prepare;
    JobTickets.Open;
  end;
end;

Заключение

Проблема, с которой столкнулся разработчик, связана с порядком инициализации формы в Delphi. Хотя перенос кода в FormShow решает проблему, более правильными подходами являются:

  1. Использование специального конструктора для передачи параметров
  2. Применение параметризованных запросов
  3. Использование AfterConstruction или сеттеров свойств

Выбор конкретного решения зависит от архитектуры вашего приложения и личных предпочтений. Главное - понимать порядок выполнения кода при создании и отображении форм в Delphi.

Для старых проектов, которые переходят на Delphi 12.3, рекомендуется провести аудит всех подобных случаев и выбрать единый подход для модернизации кода.

Создано по материалам из источника по ссылке.

Статья описывает проблему с кодом SQL-запроса в Delphi 12.3, который перестал работать в обработчике FormCreate из-за изменения порядка инициализации формы, и предлагает различные способы её решения.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: SQL ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-06-04 06:34:22/0.0059130191802979/0