Автор: admin | 14.12.2007 в 2:14 | Рубрики: Базы данных

Вся хитрость заключается в использовании StrPcopy (помещения вашей строки в PChar) и записи буфера в поток. Вы не сможете передать это в PChar непосредственно, поскольку ему нужен буфер, поэтому для получения необходимого размера буфера используйте [0] и StrLen().

Вот пример использования TMemoryStream и записи его в Blob-поле:

var
cString: string;
oMemory: TMemoryStream;
Buffer: PChar;
begin
cString := ‘Ну, допустим, хочу эту строку!’;

{ СОздаем новый поток памяти }
oMemory := TMemoryStream.Create;

{!! Копируем строку в PChar }
StrPCopy(Buffer, cString);

{ Пишем =буфер= и его размер в поток }
oMemory.Write(Buffer[0], StrLen(Buffer));

{Записываем это в поле}
< Blob / Memo / GraphicFieldName > .LoadFromStream(oMemory);

{ Необходимо освободить ресурсы}
oMemory.Free;
end;

Автор: admin | в 2:14 | Рубрики: Базы данных

1) Может ли мое приложение иметь доступ к файлам, расположенным на сетевых дисках?

Да.

2) Когда я попытался это сделать, программа выдала сообщение об ошибке “Not initialized for accessing network files” (не инициализировано для доступа к сетевым файлам).

Вероятно вам необходимо задать правильный путь к каталогу в поле ‘NET DIR’ файла IDAPI.CFG. Директория должна быть одна и быть доступна всем пользователям приложения с применением одинаковых подключенных сетевых дисков. (т.е.: если NET DIR указывает на F:\PUBLIC\NETDIR, пользователи с подключенным сетевым диском и имеющим путь G:\NETDIR доступа не получат).

3) Возможно ли запустить приложение, относящееся к описываемой категории, с сетевого диска без установленного на локальной машине BDE (за исключением возможных ссылок в локальном файле WIN.INI на копии элементов программы BDE/IDAPI, расположенных на сетевом диске)?

Да. Установите BDE в сети и затем добавьте следующие секции в файл WIN.INI каждой рабочей станции:

[IDAPI]
CONFIGFILE01=F:\IDAPI\IDAPI.CFG
DLLPATH=F:\IDAPI

[Borland Language Drivers]
LDPath=F:\IDAPI\LANGDRV

…пути должны отражать текущее месторасположение каталога IDAPI.

4) Для установки “NET DIR” мне нужно запустить BDECFG на каждой рабочей станции или просто сделать это на “сервере”?

C помощью утилиты BDECFG отредактируйте файл IDAPI.CFG и сохраните его в сетевом каталоге IDAPI. Следовательно, вам необходимо проделать данную операцию всего-лишь один раз.

5) Если мне нужно сделать это только на сервере, то как все рабочие станции узнают о месторасположении сетевых файлов (”NET DIR”)?

Рабочая станция открывает файл IDAPI.CFG из каталога, указанного в WIN.INI, и уже оттуда читает настройки NET DIR.

Типичная ошибка! BDE это не поддержка alias! компоненты Дельфи такие как Table, Query, Database - почти вообще ничего не делают! - это только удобный интерфейс к BDE. Т.е. BDE реально читает и пишет в базы данных, обнавляет файлы, управляет транзакциями, сортирует данные, исполняет SQL запросы. BDE с одной стороны имеет BDE Admin для ее управления, а с другой API, которые и использует Дельфи в компонентах. Если вам надо обойтись без BDE вы должны использовать другие драйвера доступа к базам данных: ODBC, DAO, ADO, RDO - многие из них имеют свои API или COM интерфейсы которые вы можете использовать (напрямую, либо найти компоненты для этого, кроме того ADO входит в стандартную поставку дельфей, но через него приконнектится к парадоксу довольно затруднительно). Если же все эти драйвера вас не устраивают то вам надо написать свой драйвер к базе данных (можно прямо в коде программы), он должен обеспечивать:

Чтение и запись базы
Поддержка транзакций
Исполнение SQL запросов
Поддержка индексов и ключей
Поддержка многопользовательского доступа.
Стандартный набор API которые позволят подключаться компонентам типа Table, Query
Есть так же сторонние библиотеки для доступа к базам данных через свои собственные драйвера: HALCYON, или Апполо (Предложил МММ);

vkDBF- компонент для работы с ДБФ для Дельфы6/5 без БДЕ.(Предложил Free)

unit Main;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, BDE, ExtCtrls, DBCtrls, Grids, DBGrids, Db, DBTables, Buttons;

type
TMainForm = class(TForm)
AliasesList: TComboBox;
TablesList: TComboBox;
EmptyBtn: TBitBtn;
Label1: TLabel;
Label2: TLabel;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormShow(Sender: TObject);
procedure AliasesListChange(Sender: TObject);
procedure EmptyBtnClick(Sender: TObject);
private
hDB: hDBIDB;
hCursor: hDBICur;
DBDesc: DBDesc;
TblDesc: TBLBaseDesc;
public
{ Public declarations }
end;

var
MainForm: TMainForm;

implementation

{$R *.DFM}

procedure TMainForm.FormShow(Sender: TObject);
var Rslt: DBIResult;
begin
AliasesList.Items.Clear;
TablesList.Items.Clear;
hDB := nil;
try
DbiInit(nil); // Инициализация BDE
DbiOpenDatabaseList(hCursor);
repeat
Rslt := DbiGetNextRecord(hCursor, dbiNOLOCK, @DBDesc, nil);
if (Rslt <> DBIERR_EOF) then AliasesList.Items.Add(StrPas(DBDesc.szName));
until (rslt <> DBIERR_NONE);
DbiCloseCursor(hCursor);
except
on E: EDBEngineError do ShowMessage(’Ошибка инициализации BDE’);
end;
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
try
finally
if hDB <> nil then DbiCloseDatabase(hDB); // Закрытие базы данных
DbiExit; // Закрытие сеанса работы с BDE
end
end;

procedure TMainForm.AliasesListChange(Sender: TObject);
begin
try
if hDB <> nil
then DbiCloseDatabase(hDB); // Закрытие базы данных
DbiOpenDatabase // Открытие базы данных
(
PChar(AliasesList.Text), // Псевдоним базы данных
nil, // Тип базы данных
dbiReadWrite, // Режим редактирования данных
dbiOpenShared, // Режим разделения данных
nil, // Пароль
0, // Число дополнительных параметров
nil, // Перечень полей для доп. параметров
nil, // Список доп. параметров
hDB // Дескриптор базы данных
);
DbiSetPrivateDir(’c:\temp’); // Определение временного каталога
DbiOpenTableList(hDb, False, False, ‘*.DB’, hCursor);
TablesList.Items.Clear;
TablesList.Clear;
while DbiGetNextRecord(hCursor, dbiNOLOCK, @TblDesc, nil) = dbiErr_None
do TablesList.Items.Add(TblDesc.szName);
DbiCloseCursor(hCursor);
except
on E: EDBEngineError do ShowMessage(’Ошибка открытия базы данных’);
end;
end;

procedure TMainForm.EmptyBtnClick(Sender: TObject);
begin
try
DbiEmptyTable(hDB, nil, PChar(TablesList.Text), ”);
except
on E: EDBEngineError do ShowMessage(’Неверно задана таблица’);
end;
end;

end.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, BDE, ExtCtrls;

type
TMainForm = class(TForm)
PriorBtn: TBitBtn;
Panel2: TPanel;
NextBtn: TBitBtn;
Label3: TLabel;
CountryEdit: TEdit;
Label1: TLabel;
CapitalEdit: TEdit;
procedure PriorBtnClick(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure NextBtnClick(Sender: TObject);
private
hDB: hDBIDB;
hCur: hDBICur;
CursProps: CurProps;
RecBuf: pByte;
FValue: array[0..255] of Char;
IsEmpty: Bool;
procedure OnBDEError;
public
end;

var
MainForm: TMainForm;

implementation

{$R *.DFM}

procedure TMainForm.OnBDEError;
var ErrInfo: dbiErrInfo; //Структура, содержащая информацию об ошибках
AStr: string;
begin
DbiGetErrorInfo(True, ErrInfo); //Функция возвращает информацию об ошибке
case ErrInfo.iError of
9733: AStr := ‘Для создания записи недостаточно параметров ‘;
10024: AStr := ‘Ошибка доступа к данным’;
10245: AStr := ‘База данных занята другим пользователем’;
10038: AStr := ‘Значение поля задано неверно’;
11871: AStr := ‘Несоответствие типов’;
11959: AStr := ‘В выражении отсутствует оператор GROUP BY’;
else
AStr := ‘Ошибочная операция с данными’;
end;
ShowMessage(AStr);
end;

procedure TMainForm.FormShow(Sender: TObject);
begin
hDB := nil;
hCur := nil;
DbiInit(nil); // Инициализация системы BDE
DbiOpenDatabase // Открытие базы данных
(
‘DBDEMOS’, // Псевдоним базы данных
nil, // Тип базы данных
dbiReadWrite, // Режим редактирования данных
dbiOpenShared, // Режим разделения данных
nil, // Пароль
0, // Число дополнительных параметров
nil, // Перечень полей для доп. параметров
nil, // Список доп. параметров
hDB // Дескриптор базы данных
);
DbiSetPrivateDir(’c:\temp’); // Определение временного каталога
DbiOpenTable // Открытие таблицы
(
hDB, // Дескриптор базы данных
PChar(’COUNTRY’), // Название таблицы
PChar(szParadox), // Тип таблицы (только для локальных БД)
nil, // Название индекса (необязательный)
nil, // IndexTagName - только для dBASE
0, // 0 - использовать первичный индекс
dbiReadWrite, // Режим редактирования данных
dbiOpenShared, // Режим разделения данных
xltField, // Режим трансляции данных
False, // Признак одностороннего перемещения курсора
nil, // Дополнительные параметры
hCur // Дескриптор курсора таблицы
);
DbiGetCursorProps // Определение параметров курсора
(
hCur, // Дескриптор курсора таблицы
CursProps // Структура параметров курсора
);
GetMem(RecBuf, CursProps.iRecbufSize * SizeOf(Byte)); // Выделение памяти под буфер записи
DbiSetToBegin(hCur); // Установка курсора в начало набора данных
DbiGetNextRecord // Перемещение на первую запись
(
hCur, // Дескриптор курсора таблицы
dbiNoLock, // Режим ограничения доступа
RecBuf, // Буфер записи
nil // Параметры записи
);
DbiGetField // Получение значения поля
(
hCur, // Дескриптор курсора таблицы
1, // Номер поля в структуре таблицы
RecBuf, // Буфер записи
@FValue, // Переменная, в кторую передается значение
IsEmpty // Признак пустой ячейки
);
MainForm.CountryEdit.Text := FValue;
DbiGetField(hCur, 2, RecBuf, @FValue, IsEmpty);
MainForm.CapitalEdit.Text := FValue;
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
try
finally
FreeMem(RecBuf); // Освобождение памяти буфера записи
DbiCloseCursor(hCur); // Закрытие курсора
DbiCloseDatabase(hDB); // Закрытие базы данных
DbiExit; // Закрытие сеанса работы с BDE
end
end;

procedure TMainForm.PriorBtnClick(Sender: TObject);
begin
try
if DbiGetPriorRecord(hCur, dbiNoLock, RecBuf, nil) = DBIERR_BOF
then PriorBtn.Enabled := False
else
begin
if not NextBtn.Enabled then NextBtn.Enabled := True;
DbiGetField(hCur, 1, RecBuf, @FValue, IsEmpty);
MainForm.CountryEdit.Text := FValue;
DbiGetField(hCur, 2, RecBuf, @FValue, IsEmpty);
MainForm.CapitalEdit.Text := FValue;
end;
except
OnBDEError;
end;
end;

procedure TMainForm.NextBtnClick(Sender: TObject);
begin
try
if DbiGetNextRecord(hCur, dbiNoLock, RecBuf, nil) = DBIERR_EOF
then NextBtn.Enabled := False
else
begin
if not PriorBtn.Enabled then PriorBtn.Enabled := True;
DbiGetField(hCur, 1, RecBuf, @FValue, IsEmpty);
MainForm.CountryEdit.Text := FValue;
DbiGetField(hCur, 2, RecBuf, @FValue, IsEmpty);
MainForm.CapitalEdit.Text := FValue;
end;
except
OnBDEError;
end;
end;

end.