Валентин Озеров - Советы по Delphi. Версия 1.4.3 от 1.1.2001
if PDbiCbInfo(iClientData)^.DbiCbFn <> nil then
DbiCbFn:=pfDBICallBack(PDbiCbInfo(iClientData)^.DbiCbFn)(ecbType,PDbiCbInfo(iClientData)^.iClientData,cbInfo)
else DbiCbFn := cbrCONTINUE;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
CbDataBuff: CBPROGRESSDesc; {Структура DBi}
OldDbiCbInfo : TDbiCbInfo; {структура данных должна хранить информацию о предыдущем обратном вызове}
begin
{Убедимся в том, что перемещаемая таблица открыта}
Table1.Open;
{Убедимся в том, что таблица-приемник закрыта}
Table2.Close;
{получаем информацию о любом установленном обратном вызове}
DbiGetCallBack(Table2.Handle, cbGENPROGRESS, @OldDbiCbInfo.iClientData, @OldDbiCbInfo.DataBuffLn, @OldDbiCbInfo.DataBuff, pfDBICallBack(OldDbiCbInfo.DbiCbFn));
{регистрируем наш обратный вызов}
DbiRegisterCallBack(Table2.Handle, cbGENPROGRESS, longint(@OldDbiCbInfo), SizeOf(cbDataBuff), @cbDataBuff, @DbiCbFn);
Form1.ProgressBar1.Position := 0;
BatchMove1.Execute;
{если предыдущий обратный вызов существовал - вновь устанавливаем его,}
{в противном случае "отрегистрируем" наш обратный вызов}
if OldDbiCbInfo.DbiCbFn <> nil then
DbiRegisterCallBack(Table2.Handle, cbGENPROGRESS, OldDbiCbInfo.iClientData,
OldDbiCbInfo.DataBuffLn, OldDbiCbInfo.DataBuff, OldDbiCbInfo.DbiCbFn)
else
DbiRegisterCallBack(Table2.Handle, cbGENPROGRESS, longint(@OldDbiCbInfo),
SizeOf(cbDataBuff), @cbDataBuff, nil);
{Показываем наш успех!}
Table2.Open;
end;
end.
Управление сетевыми каталогами (BDE)
Если два различных пользователя подключают два различных сетевых каталога (net control directories, NCD), но при этом пути к каталогам одинаковые (это не трудно при работе с сетью), BDE думает, что в этом случае используются одни и те же NCD. Это может привести к _огромным_ проблемам.
Если два пользователя подключают один и тот же NCD, но с разными путями, BDE думает что используются два различных NCD и не позволяет второму пользователю редактировать таблицу. Например, пользователь A подключил NCD по пути G:DATABDENET. Пользователь B подключил NCD по пути H:BDENET, где H: подключен по пути G:DATA. В этом случае оба пользователя пытаются использовать один и тот же NCD, но BDE не знает об этом.
Если в вышеприведенном примере пользователи используют один и тот же путь, но с различными буквами диска, BDE позволяет работать обоим пользователям, подразумевая, что они используют один и тот же NCD. Так, если пользователь A подключен к G:DATABDENET, а пользователь B к H:DATABDENET, BDE даст работать обоим.
Это полезно в peer-to-peer сети, где сервер также является и рабочей станцией. В этом случае некоторые (какие?) peer-to-peer OS не позволят серверу подключить сетевой диск к самому себе (я не уверен что у них невозможен эквивалент SUBST, но, по крайней мере, у тех OS, которые я знаю, это отсутствует) так что сервер может использовать только диск C: (или D:, или какой-то другой локальный диск), а рабочая станция нет, поскольку сама имеет собственный локальный диск C:.
Richard Davis
Дополнение от Mark Ostroff (Borland):
В дополнение к ИЗУМИТЕЛЬНОМУ ответу Richard'а, пожалуйста помните об одной ОЧЕНЬ важной вещи… НИКОГДА не допускайте ситуации (в ЛЮБОЙ сети), при которой вы имеете нескольких пользователей, имеющих доступ к одним и тем же таблицам, но использующих разные физические NET-файлы. Это создает ОГРОМНЫЕ проблемы, особенно в в корпоративных и peer-to-peer сетях.
Pdox DOS версии 4.0 использует ту же BDE-схему работы с сетью, что и таблицы Paradox. Необходимо учесть несколько важных моментов:
1. Убедитесь в том, что у вас включена опция BDE Local Share, если вы создаете таблицы с общим доступом для приложений Pdox DOS и BDE.
2. Из-за странного поведения при работе с сетевыми каталогами, пути в файле контроля сети Pdox DOS у ваших пользователей должны быть ИДЕНТИЧНЫ BDE путям (например, тот же каталог И та же буква диска). Это должно быть сделано в случае, если и Pdox DOS, и BDE делают общими одни и те же таблицы и запущены ОБА приложения. Это может создать некоторые проблемы с установкой peer-to-peer сетей.
3. Убедитесь в том, у вас выключена опция BDE Strict Integrity, если вы создаете таблицы с общим доступом для приложений Pdox DOS и BDE. В противном случае BDE заблокирует пользователей Pdox DOS для редактирования данных в таблицах Paradox (в любом каталоге), у которых установлена опция целостности данных (Referential Integrity).
4. Убедитесь в том, что номер версии Paradox, имеющийся в настройках BDE, совместим с OLDEST версией Pdox DOS для использования в вашей сети. Установить ее можно, выбрав соответствующий драйвер Paradox в BDE Config Utility и проверив значение в поле LEVEL. Установите номер версии Pdox DOS, округлив его до ближайшего МЕНЬШЕГО целого числа.
Пример DBIDoRestructure
Единственный способ изменить размер поля или его тип — использовать DBIDoRestructure. Вот простой пример, который может вам помочь в этом:
function BDEStringFieldResize(ATable: TTable; AFieldName: string; ANewSize: integer): boolean;
type TRestructStatus = (rsFieldNotFound, rsNothingToDo, rsDoIt);
var
hDB: hDBIdb;
pTableDesc: pCRTblDesc;
pFldOp: pCROpType; {фактически это массив array of pCROpType}
pFieldDesc: pFldDesc; {фактически это массив array of pFldDesc}
CurPrp: CurProps;
CSubType: integer;
CCbrOption: CBRType;
eRestrStatus: TRestructStatus;
pErrMess: DBIMsg;
i: integer;
begin
Result := False;
eRestrStatus := rsFieldNotFound;
AFieldName := UpperCase(AFieldName);
pTableDesc := nil;
pFieldDesc := nil;
pFldOp := nil;
with ATable do try
{убедимся что имеем исключительный доступ и сохраним dbhandle:}
if Active and (not Exclusive) then Close;
if (not Exclusive) then Exclusive := True;
if (not Active) then Open;hDB := DBHandle;
{готовим данные для DBIDoRestructure:}
BDECheck(DBIGetCursorProps(Handle,CurPrp));
GetMem(pFieldDesc,CurPrp.iFields*sizeOf(FldDesc));
BDECheck(DBIGetFieldDescs(Handle,pFieldDesc));
GetMem(pFldOp,CurPrp.iFields*sizeOf(CROpType));
FillChar(pFldOp^,CurPrp.iFields*sizeOf(CROpType),0);
{ищем в цикле (через fielddesc) наше поле:}
for i:=1 to CurPrp.iFields do begin
{для ввода мы имеем серийные номера вместоPdox ID, возвращаемых DbiGetFieldDescs:}
pFieldDesc^.iFldNum := i;
if (Uppercase(StrPas(pFieldDesc^.szName)) = AFieldName) and (pFieldDesc^.iFldType = fldZSTRING) then begin
eRestrStatus := rsNothingToDo;
if (pFieldDesc^.iUnits1 <> ANewSize) then begin
pFieldDesc^.iUnits1 := ANewSize;
pFldOp^ := crModify;
eRestrStatus := rsDoIt;
end;
end;
inc(pFieldDesc);
inc(pFldOp);
end; {for}
{"регулируем" массив указателей:}
dec(pFieldDesc,CurPrp.iFields);
dec(pFldOp,CurPrp.iFields);
{в случае отсутствия операций возбуждаем исключение:}
case eRestrStatus of
rsNothingToDo:
raise Exception.Create('Ничего не сделано');
rsFieldNotFound:
raise Exception.Create('Поле не найдено');
end;
GetMem(pTableDesc,sizeOf(CRTblDesc));
FillChar(pTableDesc^,SizeOf(CRTblDesc),0);
StrPCopy(pTableDesc^.szTblName,TableName);
{StrPCopy(pTableDesc^.szTblType,szPARADOX); {}
pTableDesc^.szTblType := CurPrp.szTableType;
pTableDesc^.iFldCount := CurPrp.iFields;
pTableDesc^.pecrFldOp := pFldOp;
pTableDesc^.pfldDesc := pFieldDesc;
Close;
BDECheck(DbiDoRestructure(hDB, 1, pTableDesc, nil, nil, nil, False));
finally
if pTableDesc <> nil then FreeMem(pTableDesc,sizeOf(CRTblDesc));
if pFldOp <> nil then FreeMem(pFldOp, CurPrp.iFields*sizeOf(CROpType));
if pFieldDesc <> nil then FreeMem(pFieldDesc, CurPrp.iFields*sizeOf(FldDesc));
Open;
end; {пробуем с table1}
Result := True;
end;
Reinhard Kalinke
Изменение конфигурации IDAPI
Delphi 1
Возможно ли установить параметр MAXFILEHANDLES в IDAPI.CFG посредством Delphi?
Да. Следующий компонент показывает как это можно сделать (а также изменить другие параметры):
unit CFGTOOL;
interface
uses SysUtils, Classes, DB, DbiProcs, DbiTypes, DbiErrs;
type TBDEConfig = class(TComponent)
private
FLocalShare : Boolean;
FMinBufSize : Integer;
FMaxBufSize : Integer;
FSystemLangDriver : String;
FParadoxLangDriver : String;