Рейтинговые книги
Читем онлайн Советы по Delphi. Версия 1.4.3 от 1.1.2001 - Валентин Озеров

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 24 25 26 27 28 29 30 31 32 ... 123

Delphi 1

Все это я делал раньше. Я не могу вам все это показать на развернутом примере, но я дам вам идею как сделать это. Вы должны иметь таблицу, осуществляющую взаимоотношение между людьми. Если на Peter работают Jane и Simon, вы должны иметь таблицу (RELATION) с этими двумя записями.

Master

Slave ------- имена полей

Peter Jane

Peter Simon

Если George и Elisa работают на Jane, то таблица становится такой:

Master Slave ------- имена полей

Peter Jane

Peter Simon

Jane George

Jane Elisa

и так далее.

Если в таблице RELATION необходимо создать дерево, начинающееся на Peter, то нужно добавить к дереву главный узел (запись), где Master = Peter. Затем каждая дочерняя запись располагается ниже записи Master = Peter. После добавления дочерней записи вы сразу увидите, если ребенок имеет собственного ребенка. Ребенок становится теперь, вероятно, отцом, поэтому вы должны позиционировать таблицу RELATION к первой записи, где Master = child, и так далее, рекурсивно. Такой способ гарантирует построение правильного дерева.

Пример:

AddFather('Peter')

AddChild('Peter',1)

Procedure AddFather(Name: String)

Begin

 Tree.Add(Name);

End;

Procedure AddChildr(Name: String, Index:Integer)

Begin

 Relation.FindKey([Name])while RelationMaster.AsString = Name do

 Begin

  Tree.AddChild(Index,RelationSlave.AsString);

  AddChild(RelationSlave.AsString,Tree.ItemsCount);

  Relation.Next;

 End;

End;

По-моему, ошибок нет.

DBGrid и Memo-поля

Delphi 1

В обработчик события GetText TMemoField поместите следующую строку:

Text := GrabMemoAsString(TMemoField(Sender));

и поместите следующую функцию так, чтобы к ней можно было свободно обратиться:

function GrabMemoAsString(TheField : TMemoField): String;

begin

 if TheField.IsNull then Result := '' else with TBlobStream.Create(TheField, bmRead) do begin

  if Size >= 255 then begin

   Read(Result[1], 255);

   Result[0] := #255;

  end else begin

   Read(Result[1], Size);

   Result[0] := Chr(Size);

  end;

  Free;

  while Pos(#10, Result) > 0 do Result[Pos(#10, Result)] := ' ';

  while Pos(#13, Result) > 0 do Result[Pos(#13, Result] := ' ';

end;

end

Убывающий индекс

Delphi 1 

Я нашел простой способ получения убывающего индекса. В Delphi это получается очень легко и красиво: 

Table1.AddIndex('NewIndex', 'CustNo;CustName', [ixDescending]); 

Как работать из Delphi напрямую с MS ADO (Microsoft Active Data Objects)?

Nomadic отвечает:

Итак, хочу поделиться некоторыми достижениями… так на всякий случай. Если у вас вдруг потребуется сделать в своей программке доступ к базе данных, а BDE использовать будет неохота (или невозможно) – то есть довольно приятный вариант: использовать ActiveX Data Objects. Однако с их использованием есть некоторые проблемы, и одна из них это как передавать Optional параметры, которые вроде как можно не указывать. Однако, если вы работаете с ADO по-человечески, а не через тормозной IDispatch.Invoke то это превращается в головную боль. Вот как от нее избавляться: 

var

 OptionalParam: OleVariant;

 VarData: PVarData;

begin

 OptionalParam := DISP_E_PARAMNOTFOUND;

 VarData := @OptionalParam;

 VarData^.VType := varError;

после этого переменную OptionalParam можно передавать вместо неиспользуемого аргумента.

Далее, самый приятный способ получения Result sets:

Там есть масса вариантов, но как выяснилось оптимальным является следующий вариант, который позволяет получить любой желаемый вид курсора (как клиентский, так и серверный) 

var

 MyConn: _Connection;

 MyComm: _Command;

 MyRecSet: _Recordset;

 prm1: _Parameter;

begin

 MyConn := CoConnection.Create;

 MyConn.ConnectionString := 'DSN=pubs;uid=sa;pwd=;';

 MyConn.Open('', '', '', –1);

 MyCommand := CoCommand.Create;

 MyCommand.ActiveConnection := MyConn;

 MyCommand.CommandText := 'SELECT * FROM blahblah WHERE BlahID=?'

 Prm1 := MyCommand.CreateParameter('Id', adInteger.adParamInput, –1, <value>);

 MyCommand.AppendParameter(Prm1);

 MyRecSet := CoRecordSet.Create;

 MyRecSet.Open(MyCommand, OptionalParam, adOpenDynamic, adLockReadOnly, adCmdText);

…теперь можно фетчить записи. Работает шустро и классно. Меня радует. Особенно радуют серверные курсоры.

Проверялось на Delphi 3.02 + ADO 1.5 + MS SQL 6.5 sp4. Пашет как зверь.

Из вкусностей ADO – их легко можно использовать во всяких многопоточных приложениях, где BDE порой сбоит, если, конечно, ODBC драйвер грамотно сделан…

Ну и еще можно использовать для доступа к данным всяких там «нестандартных» баз типа MS Index Server или MS Active Directory Services.

В Delphi (как минимум в 4 версии) существует «константа» EmptyParam, которую можно подставлять в качестве пустого параметра. 

Как засунуть в качестве паpаметpа хpанимой пpоцедуpы стpоку длиной более 255 символов? И вообще, как использовать паpаметpы SP, если они BLOB?

Nomadic отвечает:

«Засунуть» длинную строку можно было и раньше, если написать редактируемый запрос, и воспользоваться операциями Insert/Edit.

Однако это не относится к хранимым процедурам.

В Delphi 3.0 появился новый тип параметра (TBlobField вроде) и соответственно его поддержка в BDE.

Если просто взять BDE 4.01 и выше, то работать все-равно не будет – нужна соотв. версия VCL (из Delphi 3.0 или выше). 

Дублирование набора записей

Delphi 1 

Вы можете воспользоваться вторым объектом TTable, подключенным к той же таблице, или можете вызвать метод объект TTable DisableControls, сделать изменения, и вызвать EnableControls. Для сохранения той же позиции вы можете попробовать воспользоваться закладкой. Например, так:

procedure TMyForm.MakeChanges;

var

 aBookmark: TBookmark;

begin

 Table1.DisableControls;

 aBookmark := Table.GetBookmark;

 try

  {ваш код}

 finally

  Table1.GotoBookmark(aBookmark);

  Table1.FreeBookmark(aBookmark);

  Table1.EnableControls;

 end;

end;

Как программно изменить LangDriver для таблиц dBase и Paradox?

Nomadic отвечает:

Откpываешь help и смотpишь:

……

var list:tstrings;

……

BEGIN

…….

List.Add ( 'LANGDRIVER=db866ru0 ');

……

Session.ModifyDriver( 'DBASE', List );

……

END;

Это действие я пpовожy пеpед откpытием таблицы

Ivan Sboev

(2:5049/36.15)

Это о «русификации» таблицы. В таблицах dBase и Paradox имеется байт, который определяет CodePage содержимого таблицы. Раньше он не использовался и был зарезервирован. Тебе нужно его правильно установить. Это делается через DBD Restructure table. Если хочешь программно, можешь воспользоваться следующей процедурой:

uses DbiTypes, DbiProcs, DbiErrs, DB, WinProcs, SysUtils;

procedure ChangeLangDriver( DatabaseName, TableName, LDName: string );

var

 TblExt: string;

 Database: TDatabase;

 TblDesc: CRTblDesc;

 OptDesc: FLDDesc;

 OptData: array [0..250] of Char;

 Cur: hDBICur;

 Rec: CFGDesc;

begin

 if (TableName='') or (LDName='') then raise Exception.Create('Unknown TableName or LDName');

 Database:=Session.OpenDatabase(DatabaseName);

 try

  if Database.IsSQLBased then raise Exception.Create('Function ChangeLangDriver working only with dBase or Paradox tables');

  FillChar(OptDesc, SizeOf(OptDesc), #0);

  FillChar(TblDesc, SizeOf(TblDesc), #0);

  StrCopy(OptDesc.szName, 'LANGDRIVER');

  OptDesc.iLen := Length(LDName) + 1;

  with TblDesc do

  begin

   StrPCopy(szTblName, TableName);

   TblExt := UpperCase(ExtractFileExt(TableName));

   if TblExt = 'DBF' then StrCopy(szTblType, szDbase)

   else if TblExt = '.DB' then StrCopy(szTblType, szParadox)

   else

   begin

    AnsiToOEM(StrPCopy(OptData, DatabaseName), OptData);

   if DbiOpenCfgInfoList(nil, dbiREADONLY, cfgPersistent, StrPCopy(OptData, 'DATABASES' + StrPas(OptData) + 'DB INFO')Cur) <> DBIERR_NONE then raise Exception.Create('Unknown table type');

    try

     while DbiGetNextRecord(Cur, dbiNOLOCK, @Rec, nil) <> DBIERR_EOF do if StrComp(Rec.szNodeName, 'DEFAULT DRIVER') = 0 then

     begin

1 ... 24 25 26 27 28 29 30 31 32 ... 123
На этой странице вы можете бесплатно читать книгу Советы по Delphi. Версия 1.4.3 от 1.1.2001 - Валентин Озеров бесплатно.

Оставить комментарий