В противном случае вы не получите ошибку в случае, если текущую запись «рассматривает» другой пользователь (если вы пользуетесь базой данных Paradox, поставляемой с Delphi), если, конечно, вы правильно это установили. Paradox сам создает в сетевом каталоге файл с именем pdxusers.lck, видимый всеми пользователями, так что каждый BDE на каждой локальной машине может запирать запись, таким образом запрещая другим пользователям постить запись до снятия блокировки. Я не знаю, каким образом вы получаете эту ошибку, поэтому существует вероятность того, что я ошибаюсь в своих предположениях.
Каким драйвером пользуется TDATABASE?
Delphi 1
Вы можете использовать вызов IDAPI dbiGetDatabaseDesc. Вот быстрая справка (не забудьте добавить DB в список используемых модулей):
var
pDatabase: DBDrsc:
begin
{ pAlias – PChar, содержащий имя псевдонима}
dbiGetDatabaseDesc(pAlias, @pDatabase);
Для получения дополнительной информации обратитесь к описанию свойства pDatabase.szDbType.
Как создать новый запрос и скопировать туда точно такие же описания полей?
Nomadic отвечает:
Копируешь FieldDefs.
Проходишь циклом по FieldDefs.Items[i].CreateField(Owner);
Запись потока в BLOB-поле
Delphi 1
Вся хитрость заключается в использовании StrPcopy (помещения вашей строки в PChar) и записи буфера в поток. Вы не сможете передать это в PChar непосредственно, поскольку ему нужен буфер, поэтому для получения необходимого размера буфера используйте
Вот пример использования TMemoryStream и записи его в Blob-поле:
var
cString: String;
oMemory: TMemoryStream;
Buffer: PChar;
begin
cString := 'Ну, допустим, хочу эту строку!';
{ СОздаем новый поток памяти }
oMemory := TMemoryStream.Create;
{!! Копируем строку в PChar }
StrPCopy(Buffer, cString);
{ Пишем =буфер= и его размер в поток }
oMemory.Write(Buffer[0], StrLen(Buffer));
{Записываем это в поле}
{ Необходимо освободить ресурсы}
oMemory.Free;
end;
Как я могу выбрать на клиента только часть данных с определенной позиции из набора данных на сервере?
Nomadic отвечает:
Наиболее приемлемым является использование TQuery и Provider.SetParams.
Но также Вы можете сделать это иначе:
Сперва на клиенте Вам нужно считать с сервера только метаданные для набора данных. Это можно сделать, установив PacketRecords в 0, и затем вызвав Open. Затем Вы должны вызвать метод сервера (Вы должны определить этот метод на сервере), который спозиционирует курсор на первую нужную запись. И, наконец, установите PacketRecords в нужное значение, большее нуля, и вызовите GetNextPacket.
Отследить изменение данных?
Предположим, что пользователь изменил строковое поле в Null. Как тогда я в обработчике OnUpdateData смогу определить, изменилось ли это поле на строку Null, или поле просто не было изменено?
Nomadic отвечает:
Используйте свойство NewValue класса TField при чтении второй записи (той, которая содержит изменения). Если возвращаемое значение (variant) пусто или не назначено, тогда поле не было модифицировано. Здесь немного иллюстрирующего кода:
var NewVal: Variant;
begin
NewVal := DataSet.FieldByName('MyStrField').NewValue;
if VarIsEmpty(NewVal) then ShowMessage('Field was not edited')
else if VarIsNull(NewVal) then ShowMessage('Field was blanked out')
else ShowMessage('New Field Value: ' + String(NewVal));
end;
Если Вы взглянете на исходники формы RecError (в репозитории), то Вы увидите, как она использует эту информацию для вывода строки ' ' при показе ошибок синхронизации данных. На сервере Вы добавляете ограничения уровня записи, используя свойство Constraints Вашего TQuery/TTable или ограничения уровня поля, используя постоянные обьекты TField (с помощью FieldsEditor либо на CustomConstraint, либо ImportedConstraint). Если Вы используете ограничения уровня поля, они вступают в силу, когда данныеотправляются в поле (например, когда Вы уходите из органа управления, связанного с этим полем (типа TDBEdit)).