В данном посте будем учиться делать выборку Select. Для этого нужно провести подготовительную работу на сервере, обновить класс методов сервера у клиента, и вызывать соответствующие методы со стороны клиента. Всего существует 3 способа –
Через TServerMethods. На мой взгляд менее удобный в смысле трудоемкости (особенно для select). Нет зависимости от COM. (Рассмотрим в других постах, так как надо будет менять набор компонентов)
Через провайдеры и прямую отправку SQL запросов. На мой взгляд более удобный – менее трудоемкий. Есть зависимость от COM. (Рассмотрим здесь)
Через провайдеры и методы ClientDataSet – (Commandtext,Insert, Edit, Delete) Самый легкий способ.(Рассмотрим здесь)
В данном посте рассмотрю только способы – через провайдеры как более простой и удобный на мой взгляд. Новый способ рассмотрю в других постах.
И в том и в другом случае нужно будет действовать по следующей примерной схеме…
Здесь под сервером подразумевается сервер приложений DataSnap.
SELECT через провайдеры и прямую отправку SQL запросов
Для начала воспользуемся старым способом – через провайдеры. В Он на мой взгляд более простой и удобный. Тем более, что в предыдущем посте про создание клиентского приложения, мы как раз создали набор компонентов для работы черед провайдеры.
Подготовительные работы на сервере приложений DataSnap
Предположим, что на сервере приложений, в модуле методов, – у нас все выглядит так…
Скажу сразу, что для того, чтобы сделать select, есть более простой способ, но для этого нужно будет поменять набор компонентов – вместо SQLDataSet1 поставить SQLQuery. Но об этом в конце данного поста.
Нам нужно остановить сервер и внести некоторые изменения в модуль методов сервера, а затем перекомпилировать его и запустить заново. В секцию public юнита методов сервера добавим следующие методы…
1 2 3 |
procedure CloseDataSet; Procedure OpenDataSet; procedure CommandText(text:string); |
И создадим для них следующую реализацию…
1 2 3 4 |
procedure TServerMethods1.CloseDataSet; begin sqldataset.Close; end; |
1 2 3 4 |
procedure TServerMethods1.OpenDataSet; begin Sqldataset.Open; end; |
1 2 3 4 |
procedure TServerMethods1.CommandText(text: string); begin sqldataset.CommandText := text; end; |
Что нужно сделать на клиенте?
-Для начала если включен сервер – отключить и включить SQLConnection (свойство Active). Иначе при генерации классов (следующий шаг) может возникнуть ошибка;
-Далее создаем / обновляем классы сервера у клиента (здесь по сути идет дублирование, но дублируются только названия, по которым можно “дергать” сами методы сервера). В контекстном меню Generate DataSnap client classes (и так каждый раз при изменении методов сервера приложений DataSnap)
-Далее если Вы нажали в первый раз на генерацию классов – создастся юнит с методами сервера, назовите его, например ClientMethods и подключите к главной форме клиентского приложения. Если не первый раз – юнит просто обновится. Хотя у меня бывали случаи когда при существовании ClientMethods генерился другой юнит с новым набором классов сервера – в этом случае просто переподключал.
-Далее, создаем кнопку на форме клиентского приложения DataSnap и вешаем на неё обработчик
Первый рабочий вариант для select…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
procedure TForm.ButtonClick(Sender: TObject); var smc: TServerMethods1Client; begin smc := TServerMethods1Client.Create(Sqlconnection.DBXConnection); try smc.CloseDataSet; {Закрываем множество на сервере} smc.CommandText('select * from mytable where primary_key > 5'); smc.OpenDataSet; Clientdataset.Close; Clientdataset.Open; finally smc.Free; end; end; |
Второй рабочий вариант для select…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
procedure TForm.ButtonClick(Sender: TObject); var smc: TServerMethods1Client; begin smc:=TServerMethods1Client.Create(Sqlconnection1.DBXConnection); try ClientDataSet.Close; smc.CloseDataSet; // метод закрытия множества на сервере - создал его в ручную ClientDataSet.CommandText := 'select * from mytable where primary_key > 5'; // PoAllowCommandText в True ClientDataSet.Open; // метод открытия множества на сервере - создал его в ручную SMC.OpenDataSet; finally smc.Free; end; end; |
Под рабочими вариантами я подразумеваю то, что работало у меня. Вот результат…
SELECT через ClientDataSet1.Commandtext
Лучший рабочий вариант…
Для этого нужно поменять набор компонентов на сервере…
Какие ещё изменения в данном случае? Здесь это изменение делать не обязательно, но оно понадобится для ApplyUpdates, Insert,Edit,Delete в последующих постах…
В методах сервера, у компонента DataSetProvider1 пишем название таблицы с которой будем работать…
1 2 3 4 5 |
procedure TServerMethods1.DataSetProvider1GetTableName(Sender: TObject; DataSet: TDataSet; var TableName: string); begin TableName:='MyTable'; end; |
Иначе система, возможно, будет ошибаться. Если меняем таблицу, с которой будем работать – здесь её тоже нужно поменять.
В принципе, чисто теоретически, код может быть ещё короче, если на сервере подключать через Sqlquery (при этом заполнить свойство Sql, например у меня был такой запрос select*from mytable ), а не через Sqldataset. тогда можно сделать таким образом…
1 2 3 |
Clientdataset1.CommandText := 'select * from mytable where primary_key>5'; Clientdataset1.Close; Clientdataset1.Open; |
На мой взгляд, это пока что лучший вариант для получения множества на клиенте. Результат работы запроса точно такой же…
Дополнительная информация
Сначала у меня сначала лучший рабочий вариант не прокатывал. Возникала ошибка на сервере приложений – “Cannot perform thos operation on an open DataSet”. На данном форуме я также развернул целую дискуссию по этому поводу. Но потом все чудесным образом заработало.
Также, я подумал, может работа через провайдеры подменяет запрос на sqlquery? Но нет! Простая проверка показала, что запрос остается тот же…