KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Валентин Озеров - Советы по Delphi. Версия 1.4.3 от 1.1.2001

Валентин Озеров - Советы по Delphi. Версия 1.4.3 от 1.1.2001

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Валентин Озеров, "Советы по Delphi. Версия 1.4.3 от 1.1.2001" бесплатно, без регистрации.
Перейти на страницу:

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

function AgeStr(aDate: TDateTime): string;

var

 DaysOld: Double;

 Years, Months: Integer;

begin

 DaysOld:= Date – aDate;

 Years:= Trunc(DaysOld / 365.25);

 DaysOld:= DaysOld – (365.25 * Years);

 Months:= Trunc(DaysOld / 30.41);

 Result:= Format('%d лет, %d месяцев',[Years, Months]);

end;

В моем случае метод OnCalcFields выглядит так:

procedure TEntryForm.TableNameOrderCalcFields(DataSet: TDataset);

begin

 TableNameOrderAge.AsString := AgeStr(TableNameOrderDateOfBirth.AsDateTime);

end

Как пересчитать все вычисляемые поля (Calculated fields) без переоткрытия TDataSet?

Одной строкой

Nomadic отвечает:

Resync([rmExact, rmCenter]);

Как создать вычисляемые поля во время исполнения программы (Calculated fields at RunTime)?


Nomadic отвечает:

Смотрите книгу "Developing Custom Delphi Components" от Рэя Конопки.

Здесь немного исправленный пример из этой книги


function TMyClass.CreateCalcField(const AFieldName: string; AFieldClass: TFieldClass; ASize: Word): TField;

begin

 Result := FDataSet.FindField( AFieldName ); // Field may already exists!

 if Result<>nil then Exit;

 if AFieldClass = nil then

 begin

  DBErrorFmt( SUnknownFieldType, [AFieldName] );

 end;

 Result := FieldClass.Create( Owner );

 with Result do

 try

  FieldName := AFieldName;

  if (Result is TStringField) or (Result is TBCDField) or (Result is TBlobField) or (Result is TBytesField) or (Result is TVarBytesField) then

  begin

   Size := ASize;

  end;

  Calculated := True;

  DataSet := FDataset;

  Name := FDataSet.Name + AFieldName;

 except

  Free; // We must release allocated memory on error!

  raise;

 end;

end

Доступ 

Хитрости многопользовательского доступа к БД

Вот некоторые хитрости, могущие помочь в разработке баз многопользовательского доступа:

В модуле DBIPROCS Delphi 1.0 и в BDE.INT 2.0 существует классная функция с именем DBISETLOCKRETRY(n).

Синтаксис – DBISetLockRetry(n), где n – количество секунд ожидания перед повторной попыткой вставки, редактирования или другой операцией с таблицей. DBISetLockRetry(-1) будет бесконечно пытаться получить доступ к вашей таблице.

Хорошее место для вызова функции – обработчик события TableAfterOpen. В этом случае все, что вам нужно сделать, это:

DBISetLockRetry(x);

Если вы используете Delphi 1.0, не забудьте включить в вашу программу DBIProcs. В Delphi 2.0 включите BDE.

Мой заказчик и я разработали многопользовательскую базу данных по вашему рецепту, до этого наши пользователи получали сообщения «File is Locked» (файл заблокирован), «Table is Busy» (таблица занята), «Record Locked» (запись заблокирована) и др. Мы также пробовали Session.Netdir, но он не помог нам. Поскольку мы добавили в код эту строку, никаких блокировок не было. Частота обращений пользователей к базе достаточно велика (80 kpm). Мы разработали «измеритель скорости доступа» с 2 открытыми сессиями на двух компьютерах в сети Novell 4.1. Две сессии занимались вставкой, две другие редактированием, а мы сами занимались посылкой данных с частотой около 65 записей в минуту в течение операций редактирования и 85 в течение вставки. Сеть чуть не захлебнулась от такой работы. Утилизация файлового сервера была до нас около 60%. Не плохо для всего! Я думаю Borland необходимо задокументировать такой подход, чтобы другие не становились хакерами типа нас! :)

Эти требования обязательны при разработке многопользовательских приложений Delphi с использованием файлов Dbase или Paradox.

– Ted Bulmanski

Выполнение запросов к базе данных в фоне

Delphi 2

Тема: Выполнение запросов к базе данных в фоновом потоке

Данный документ объясняет как выполнить запрос в фоновом режиме, используя класс TThread. Для получения общей информации о классе TThread, пожалуйста обратитесь к документации Borland и электронной справке. Для понимания данного документа вам необходимо иметь представление о том, как работать с компонентами для работы с базами данных, поставляемых в комплекте с Delphi 2.0.

Для осуществления потокового запроса необходимо выполнение двух требований. Во-первых, потоковый запрос должен находиться в своей собственной сессии с использованием отдельного компонента TSession. Следовательно, на вашей форме должен находиться компонент TSession, имя которого должно быть назначено свойству SessonName компонента TQuery, используемого для выполнения потокового запроса. Для каждого используемого в потоке компонента TQuery вы должны использовать отдельный компонент TSession. При использовании компонента TDataBase, для отдельного потокового запроса должен также использоваться отдельный TDataBase. Второе требование заключается в том, что компонент TQuery, используемый в потоке, не должен подключаться в контексте это потока к TDataSource. Это должно быть сделано в контексте первичного потока.

Приведенный ниже пример кода иллюстрирует описываемый процесс. Данный модуль демонстрирует форму, которая содержит по два экземпляра следующих компонентов: TSession, TDatabase, TQuery, TDataSource и TDBGrid. Данные компоненты имеют следующие значения свойств:

Session1

 Active True;

 SessionName "Ses1"


DataBase1

 AliasName "IBLOCAL"

 DatabaseName "DB1"

 SessionName "Ses1"


Query1

 DataBaseName "DB1"

 SessionName "Ses1"

 SQL.Strings "Select * from employee"


DataSource1

 DataSet ""


DBGrid1

 DataSource DataSource1


Session2

 Active True;

 SessionName "Ses2"


DataBase2

 AliasName "IBLOCAL"

 DatabaseName "DB2"

 SessionName "Ses2"


Query2

 DataBaseName "DB2"

 SessionName "Ses2"

 SQL.Strings "Select * from customer"


DataSource2

 DataSet ""


DBGrid1

 DataSource DataSource2

Обратите внимание на то, что свойство DataSet обоих компонентов TDataSource первоначально никуда не ссылается. Оно устанавливается во время выполнения приложения, и это проиллюстрировано в коде.

unit Unit1;


interface


uses Windows, Messages, SysUtils, Classes, Graphics, Controls,Forms, Dialogs,StdCtrls, Grids, DBGrids, DB, DBTables;


type

 TForm1 = class(TForm)

  Session1: TSession;

  Session2: TSession;

  Database1: TDatabase;

  Database2: TDatabase;

  Query1: TQuery;

  Query2: TQuery;

  DataSource1: TDataSource;

  DataSource2: TDataSource;

  DBGrid1: TDBGrid;

  DBGrid2: TDBGrid;

  GoBtn1: TButton;

  procedure GoBtn1Click(Sender: TObject);

 end;


 TQueryThread = class(TThread)

 private

FSession: TSession;

  FDatabase: TDataBase;

  FQuery: TQuery;

  FDatasource: TDatasource;

  FQueryException: Exception;

  procedure ConnectDataSource;

  procedure ShowQryError;

 protected

  procedure Execute; override;

 public

  constructor Create(Session: TSession; DataBase: TDatabase; Query: TQuery; DataSource: TDataSource); virtual;

 end;


var Form1: TForm1;


implementation


constructor TQueryThread.Create(Session: TSession; DataBase: TDatabase; Query: TQuery; Datasource: TDataSource);

begin

 inherited Create(True); // Создаем поток c состоянием suspendend

 FSession := Session;     // подключаем все privat-поля

 FDatabase := DataBase;

 FQuery := Query;

 FDataSource := Datasource;

 FreeOnTerminate := True; // Устанавливаем флаг освобождения потока после его завершения

 Resume;                  // Продолжение выполнения потока

end;


procedure TQueryThread.Execute;

begin

 try

{ Выполняем запрос и подключаем источник данных к компоненту TQuery, вызывая ConnectDataSource из основного потока(для этой цели используем Synchronize)}

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*