1.После того, как я использовал правый щелчок мыши для создания функции-провайдера, как мне снова выполнить команду контекстного меню "Export from Table"?

2.Как я могу избавиться от "зарегистрированного" имени сервера, если я не хочу использовать его далее?

3.Как осуществить минимальный тест на корректность глобального идентификатора (GUID), и интерфейсы, унаследованные от IDispatch (и, следовательно, поддерживающих методы автоматизации)?

4.Почему мои ISAPI-ориентированные библиотеки, созданные в Delphi 3, не могут обрабатывать несколько соединений?

5.Как я могу выбрать на клиента только часть данных с определенной позиции из набора данных на сервере?

6.Когда я применяю ApplyApdates на ClientDataSet, на серверной стороне не срабатывает событие OnNewRecord для оригинального набора данных. Как это исправить?

7.В чем разница между сокетами, DCOM и ELE Enterprise при использовании их в качестве транспорта?

8.Предположим, что пользователь изменил строковое поле в Null. Как тогда я в обработчике OnUpdateData смогу определить, изменилось ли это поле на строку Null, или поле просто не было изменено?

9.Что я получаю от наличия ConstraintBroker (брокера ограничений)?

10.Нужны ли мне формы в сервере приложений?

11.Как достучаться до методов сервера приложений из TClientDataSet?

12.Я включил dbclient.dll в секцию "additional files" опций распространения по web, но этот файл никогда не загружается на клиент. Как это исправить?

13.Как я могу определить доступные сервера приложений на этой машине через Registry?

14.Как передать UserName и Password в удаленный модуль данных (remote datamodule)?

15.Как можно использовать TClientDataSet в локальном приложении с таблицами Paradox, без использования компонент TProvider и TRemoteServer?

16.Как работать с новыми, своими интерфейсами в RemoteDateModule?


Q>: После того, как я использовал правый щелчок мыши для создания функции-провайдера, как мне снова выполнить команду контекстного меню "Export from Table"?

A>: Как только Вы экспортировали интерфейс провайдера, эта команда контекстного меню перестает быть видимой. Чтобы снова включить ее, Вы должны удалить ассоциированное свойство в Редакторе Библиотеки Типов, и затем нажать кнопку обновления информации в Редакторе Библиотеки Типов (Type Library Editors Refresh button). Вы могли бы также удалить точку вхождения "Get_XXX" в исходном тексте RemoteDataModule.


Q>: Как я могу избавиться от "зарегистрированного" имени сервера, если я не хочу использовать его далее?

A>: Запустите исполняемый файл сервера с ключом /UNREGSERVER: MYSERVER.EXE /UNREGSERVER Это обычный путь разрегистрации саморегистрирующего сервера автоматизации OLE.


Q>: Как осуществить минимальный тест на корректность глобального идентификатора (GUID), и интерфейсы, унаследованные от IDispatch (и, следовательно, поддерживающих методы автоматизации)?

A>: Вызовите CreateRemoteComObject, передав GUID интерфейса и имя компьютера, к которому Вы пытаетесь подключиться. Если функция вернет ошибку, то наличествует проблема сервера, иначе возможная проблема относится к клиенту.
const
MyGUID = '{444...111}'; //Whatever the guid is...

var
Unk: IUnknown;
Disp: IDispatch;

begin

{ Make sure this line works correctly }
Unk := CreateRemoteComObject('server1',
StringToGUID(MyGUID));

{ If it does, then cast it to a IDispatch }
Disp := Unk as IDispatch;

end;

Если этот кусок кода работает, а проблема остается, то Вам требуется шаг за шагом пройти через код клиента и найти, где он дает трещину. Если не сможете этого обнаружить, Вам придется запустить сервер под отладчиком и установить связь с клиентом, чтобы Вы могли произвести отладку рядом со местом, дающем слабину.


Q>: Почему мои ISAPI-ориентированные библиотеки, созданные в Delphi 3, не могут обрабатывать несколько соединений?

A>: Волшебник по созданию ISAPI DLL в Delphi 3 создает полностью безопасную многопоточную библиотеку, но не выставляет флаг, говорящий приложению, что эта библиотека в этом отношении безопасна. Это легко исправить, просто добавив строчку:
IsMultiThread := TRUE;
первой строкой в Вашем блоке begin-end файла проекта (DPR).


Q>: Как я могу выбрать на клиента только часть данных с определенной позиции из набора данных на сервере?

A>: Наиболее приемлемым является использование TQuery и Provider.SetParams. Но также Вы можете сделать это иначе: Сперва на клиенте Вам нужно считать с сервера только метаданные для набора данных. Это можно сделать, установив PacketRecords в 0, и затем вызвав Open. Затем Вы должны вызвать метод сервера (Вы должны определить этот метод на сервере), который спозиционирует курсор на первую нужную запись. И, наконец, установите PacketRecords в нужное значение, большее нуля, и вызовите GetNextPacket.


Q>: Когда я применяю ApplyApdates на ClientDataSet, на серверной стороне не срабатывает событие OnNewRecord для оригинального набора данных. Как это исправить?

A>: Никак. Эти обновления идут прямо через BDE, а не через компонент набора данных. Как обычно, можно посоветовать использование хранимых процедур, в данном контекте это будут методы сервера приложений. К сожалению, совет неприемлем для транспорта Sockets.


Q>: В чем разница между сокетами, DCOM и ELE Enterprise при использовании их в качестве транспорта?

A>: Sockets (TCP/IP): - на клиентах и сервере требуется наличие стека TCP/IP; - не требуется дополнительной настройки клиентов; DCOM: - на клиентах и серверах требуется наличие DCOM (входит в состав Windows NT 4.0, для Windows'95 доступен как опция) - требуется настройка клиентов (DCOM Configuration Utility - DCOMCNFG.EXE); - встроенная поддержка модели безопасности Windows NT; - поддержка обратных вызовов (методов). OLE Enterprise: - на клиентах и серверах требуется наличие OLE Enterprise; - требуется настройка клиентов; - поддержка обратных вызовов (методов).


Q>: Предположим, что пользователь изменил строковое поле в Null. Как тогда я в обработчике OnUpdateData смогу определить, изменилось ли это поле на строку Null, или поле просто не было изменено?

A>: Используйте свойство 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 (в репозитории), то Вы увидите, как она использует эту информацию для вывода строки '<Unchanged>' при показе ошибок reconcile. На сервере Вы добавляете ограничения уровня записи, используя свойство Constraints Вашего TQuery/TTable или ограничения уровня поля, используя постоянные обьекты TField (с помощью FieldsEditor либо на CustomConstraint, либо ImportedConstraint). Если Вы используете ограничения уровня поля, они вступают в силу, когда данные отправляются в поле (например, когда Вы уходите из органа управления, связанного с этим полем (типа TDBEdit)).


Q>: Что я получаю от наличия ConstraintBroker (брокера ограничений)?

A>: ConstraintBroker позволяет Вам включать проверки на ограничения в данные. Это означает, что когда Вы запрашиваете данные, Вы получаете правила. Эти правила автоматически без дополнительного кода входят в силу Поскольку это происходит без единой строчки кода, то Вам не требуется переписывать или обновлять приложение каждый раз при изменении правил. Фактически это простое решение задачи обновления клиентского приложения без выхода из него. Каждое приложение, использующее ConstraintBroker, автоматически получает это качество.


Q>: Нужны ли мне формы в сервере приложений?

A>: Да. Необязательно, чтобы они были видимы, но должна присутствовать хотя бы одна. Чтобы сделать главную форму невидимой, установите
Application.ShowMainForm := False

в файле проекта.
Пример:

begin
Application.ShowMainForm := False;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.


Q>: Как достучаться до методов сервера приложений из TClientDataSet?

A>: Вот так:
RemoteServer.AppServer.MyMethod.AppServer -
свойство только для чтения, возвращающее интерфейс удаленного
сервера, возвращаемый провайдером сервера приложений. Клиентские приложения
могут общаться напрямую с сервером приложений через этот интерфейс.


Q>: Я включил dbclient.dll в секцию "additional files" опций распространения по web, но этот файл никогда не загружается на клиент. Как это исправить?

A>: Ваш INF-файл должен включать в себя строки наподобие:

============
[Add.Code]
dbclient.dll=dbclient.dll
[dbclient.dll]
file=http://yoursite.com/dbclient.cab
clsid={9E8D2F81-591C-11D0-BF52-0020AF32BD64}
RegisterServer=yes
FileVersion=4,0,0,36
============
Замените "yoursite" Вашим HTTP-адресом, где находится cab-файл. FileVersion - это версия ффайла в Вашем cab-файле your CAB file (check the version information of DBCLIENT FileVersion - это версия файла в Вашем cab-файле (проверьте информацию о версии DBCLIENT, чтобы быть уверенным в соответствии). Убедитесь, что FileVersion относится к версии Вашего DBCLIENT.DLL. Вы можете положить dbclient.dll в cab-файл, используя утилиту CABARC, которую Вы найдете в папке delphi\bin. Примерная команда вызова CABARC может выглядеть примерно так:
CABARC N DBCLIENT.CAB DBCLIENT.DLL


Q>: Как я могу определить доступные сервера приложений на этой машине через Registry?

A>: Прочитайте ключ под HKEY_CLASSES_ROOT\CLSID\*, просматривая его насчет ключей, которые имеют подключ "Borland DataBroker". Эти вхождения и являются серверами приложений. Ниже пример, который загружает имена доступных серверов приложений в Listbox:
procedure TForm1.FormCreate(Sender: TObject);
var
uses Registry;
I: integer;
TempList: TStringList;
begin
TempList := TStringList.Create;
try
with TRegistry.Create do
try
RootKey := HKEY_CLASSES_ROOT;
if OpenKey('CLSID', False) then
GetKeyNames(TempList);
CloseKey;
for I := 1 to TempList.Count - 1 do
if KeyExists('CLSID\' + TempList[I]
+ '\Borland DataBroker') then
begin
if OpenKey('CLSID\' + TempList[I] + '\ProgID', False)
then begin
Listbox1.Items.Add(ReadString(''));
CloseKey;
end;
end;
finally
Free;
end;
finally
TempList.Free;
end;
end;


Q>: Как передать UserName и Password в удаленный модуль данных (remote datamodule)?

A>: В Удаленный Модуль Данных бросьте компонент TDatabase, затем добавьте процедуру автоматизации (пункт главного меню Edit | Add To Interface) для Login. Убедитесь, что свойство HandleShared компонента TDatabase установлено в True.
procedure Login(UserName, Password: WideString);
begin
{ DB = TDatabase }
{ Something unique between clients }
DB.DatabaseName := UserName + 'DB';
DB.Params.Values['USER NAME'] := UserName;
DB.Params.Values['PASSWORD'] := Password;
DB.Open;
end;
После того, как Вы создали этот метод автоматизации, Вы можете вызывать его с помощью:
RemoteServer1.AppServer.Login('USERNAME','PASSWORD');


Q>: Как можно использовать TClientDataSet в локальном приложении с таблицами Paradox, без использования компонент TProvider и TRemoteServer?

A>: Вы не сможете отделаться от Провайдера (хотя бросать его на форму/модуль данных не придется), но Вы сможете использовать TClientDataSet в одно-точечном (single-tier) приложении. Для того, чтобы открыть Client DataSet, Вы должны назначить Провайдера Данных вручную.
{ CDS = TClientDataSet }
{ Table1 = TTable }
CDS.Provider := Table1.Provider;
CDS.Open;
Также Вы должны включить модуль BDEProv в предложение Uses.


Q>: Как работать с новыми, своими интерфейсами в RemoteDateModule?

A>: В редакторе библиотеки типов (typelib) Вы можете добавить свои интерфейсы и сделать их членами оригинального coClass. После этого Вы можете обращаться к этим интерфейсам, используя следующий синтаксис:
(IDispatch(RemoteServer.AppServer) as IAnother) Необходимо заметить, что это будет работать только, если Вы используете DCOM как транспорт.

Hosted by uCoz