Форум программистов, компьютерный форум, киберфорум
Delphi: Базы данных
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.67/118: Рейтинг темы: голосов - 118, средняя оценка - 4.67
9 / 9 / 4
Регистрация: 11.07.2012
Сообщений: 200
1

Ликбез по DataSnap

30.01.2015, 23:54. Показов 22410. Ответов 30
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всех приветствую,
предлагаю открыть дисскусию по теме технологии DataSnap (трехзвенка от создателей delphi)

интересна любая информация по данной технологии
(в идеале ссылку на рабочий проект - только не такой ,как в папке sampels, что в комплекте с delphi
в котором во первых черт ногу сломит, во вторых того что нужно все равно нет, а сделанный самостоятельно )

Те кто пытался самостоятельно разобраться, по книгам и учебным примерам думаю меня поймут.

И так цель: есть одноранговая локальная сеть TCP/IP

1й Компьютер: (ОС Win7. Установлена Delphi XE7 Architect)

Лежит база firebird (2.5/3 диалект/win1251) в ней всего одна таблица - "clients"
Запущен сервер приложений datasnap - в качестве службы Windows.
На форме клиентского приложения VCL. есть таблица dbgrid и кнопки под ней

"Вставить" "Изменить" "Удалить" "Найти запись"

также присутствует кнопка "ПОДКЛЮЧИТСЯ/ОТКЛЮЧИТСЯ" и несколько Edit-ов
для внесения параметров (логин/пароль/ip адрес сервера приложений/порт/протокол)


2й Компьютер: ОС WinXP Только тонкий клиент (приложение VCL)
3й Компьютер: ОС Win7 Только тонкий клиент (приложение VCL)

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


А вот, что я выяснил за 2 недели исследований:

1. Самое главное, данный проект можно реализовать 2мя путями
"по старому" - DataSnap до delphi 2010 ( клиент на основе провайдера TDSProvidrConnection)
"по новому" - DataSnap delphi 2010, XE,XE2,........ (клиент на базе компонента TSqlServerMethod)

меня прежде всего интересует "по новому" ибо (цитирую Осипова ниже) (но и по старому интересно)

"Использование провайдеров наборов данных TDataSetProvider и TDSProviderConnection в проектах DataSnap
целесообразно лишь в том случае, когда клиентское приложение должно работать на основе интерфейса
IAppServer -т.е. для совместимости со старыми проектами зависимыми от COM .....................
Основное достоинство новой DataSnap — избавление от зависимости от COM, что позволило создавать более
простые и производитель-ные приложения"

не буду корчить из себя знатока - совершенно не представляю, что в итоге дает мне на практике
эта независимость от COM но я делаю проект с нуля и хочу, чтобы он был универсальным и актуальным.
Подозреваю, что будет легче "портировать" тонкий клиент на другие оси (не мелкософтные).

ТЕПЕРЬ В КРАТЦЕ:

по старому:

сервер Firebird - ТSQLconnection - ТSQLdataset - DataSetProvaider
- SQLquery


(причем у ТSQLdataset интересны 2 свойства это CommandType и Commandtext)
В CommandText передается инструкция SQL если в CommandType выбранно stQuery, но надо не
забыть поставить флаг poAllowCommandText в опциях.

клиент ТSQLconnection - DSProviderConnection - ClientDataSet1 - DataSource1 - DBGrid

(есть один нюанс клиент не будет работать если на компьютере с клиентом не зарегистрирована библиотека
midas.dll) Сразу вопрос, а если "по новому" - нужна эта midas.dll на клиенте? .. нет, а что нужно?

по новому:

сервер Firebird - ТSQLconnection - ТSQLdataset -SQLquery

клиент ТSQLconnection - SqlServerMethod - - DataSetProvaider - ClientDataSet1 - DataSource1 - DBGrid

(здесь все sql запросы передаются через параметры серверных методов - ниже есть пример)

(отступление) в посте (ISAPI, MySQL и DataSnap XE2. от 26/08/2012 Vlad 11 Комментарии Delphi в Web )

сказано цитирую:
"Теперь настроим TSQLServerMethod. Вообще, этот компонент удобно использовать в том случае,
если нам необходимо получить данные только для чтения. " и
"В приведенном выше примере клиента мы создали вот такую связь компонентов:
ТSQLconnection - SqlServerMethod - - DataSetProvaider - ClientDataSet1 - DataSource1 - DBGrid
Для чтения данных с сервера этого достаточно, для модификации — нет. Напишем теперь клиентское
приложение, которое будет и читать и модифицировать данные." Далее автор реализует вариант
"по старому" причем не с механизмом Commandtext, а с пресловутым dbnavigatorom, что есть не серьезно

Так вот - это не правда с помощью SqlServerMethod данные прекрасно редактируются.
Совсем другой вопрос, как в реальном времени обновлять данные в DBGrid не включая и не выключая
постоянно ТSQLconnection. Связь (TDSProvidrConnection-DataSetProvaider) сама рулила обновлением
данных (там и команда нужная имеется ApplyUpdate) достаточно было открыть/закрыть ClientDataSet1
рвать ТSQLconnection было не нужно.

Я добился конечно видимости - реальной работы с данными через тонкий клиент только при помощи
SqlServerMethod но что будет дальше если я захочу встроить например механизм транзакций ?
Не помешает постоянное отключение/включение ТSQLconnection ?

Так как я читал все подряд, то мой проект сначала получился комбинированным т.е на форме
присутствовали как компоненты - провайдеры так и SqlServerMethod и удивительное дело
все это вместе работало - а точнее "Вставить" "Изменить" "Удалить" работали через SqlServerMethod
в то время как DBGrid обнавляли провайдеры в тчении одного подключения ТSQLconnection

ЧТО Я НЕ СМОГ ПОБЕДИТЬ

1. "Найти запись" - я не смог передать sql запрос SELECT из клиента в сервер не "по старому " не "по новому"
Господин Осипов к величайшему сожалению показал только пример с Insert , по которому я и реализовал
Delet и Update. как правильно обновить ClientDataSet1 через метод - не понимаю
"по старому " через Commandtext не так интересно но тоже пока не получается

2. Я не могу заставить работать клиент на машине где нет delphi, сервер - могу. Т.Е

1й Компьютер (клиент) ----------- 2й Компьютер (сервер) работает
1й Компьютер (клиент) ----------- 3й Компьютер (сервер) работает
1й Компьютер (сервер) ----------- 2й Компьютер (клиент) не работает
1й Компьютер (сервер) ----------- 3й Компьютер (клиент) не работает

Пишет мол Error Asess Violation xxxxxx Not READ adress 00000000000000 ну то есть имеется
попытка доступа к чемуто , что пока/или уже (nil)

3. Как правильно организовать процедуру самого подключения, особенно меня интереует запрос
имени и пароля

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
   if DataModule2.SQLConnection1.Connected then
   begin
      //Закрыть соединение
      DataModule2.ClientDataSet1.Close;
      DataModule2.SQLConnection1.Close;
      BConnect.Caption:='Подключиться';
      ComboBoxSetIP.Enabled:=True;
      ComboBoxSetIP.Color:=clWindow;
      ComboBoxSetProtocol.Enabled:=True;
      ComboBoxSetProtocol.Color:=clWindow;
      ELogin.Enabled:=True;
      ELogin.Color:=clWindow;
      EPass.Enabled:=True;
      EPass.Color:=clWindow;
      EPort.Enabled:=True;
      EPort.Color:=clWindow;
   end
         else
   begin
      //устанавливаем параметры подключения
      with DataModule2.SQLConnection1 do
      begin
      //Params.Values['DriverUnit']:= 'Data.DBXDataSnap';
      Params.Values['CommunicationProtocol']:= ComboBoxSetProtocol.Text;
      Params.Values['HostName']:= ComboBoxSetIP.Text;
      Params.Values['Port']:= EPort.Text;
      //Params.Values['DatasnapContext']:= 'datasnap/';
      //Params.Values['Password']:= EPass.Text;
      //имя пользователя
      //Params.Values['DSAuthUser']:=ELogin.Text;
      //пароль
      //Params.Values['DSAuthPassword']:=EPass.Text;
      //пробуем подключиться
      //Params.SaveToFile('C:\1.txt');
      Open;
      end;
 
      Label2.Caption:=DataModule2.SQLConnection1.Params.Values['HostName'];
 
      if DataModule2.SQLConnection1.Connected then
      begin
      DataModule2.ClientDataSet1.Open;
      BConnect.Caption:='Отключиться';
      ComboBoxSetIP.Enabled:=False;
      ComboBoxSetIP.Color:=clSilver;
      ComboBoxSetProtocol.Enabled:=False;
      ComboBoxSetProtocol.Color:=clSilver;
      ELogin.Enabled:=False;
      ELogin.Color:=clSilver;
      EPass.Enabled:=False;
      EPass.Color:=clSilver;
      EPort.Enabled:=False;
      EPort.Color:=clSilver;
      end;
   end;
то что авторизацию можно сделать либо на уровне СУБД либо на уровне datasnap я смутно представляю
мне интересен вариант - datasnap
но когда я делаю свойство ТSQLconnection Loginpromt - True то выскакивает окошко, а как сделать
в своей форме ?
и еще один момент, реакцию на вводимые данные в edit по портам, протоколам, ip я наблюдаю но
если клиент и сервер на одной машине (где делфи) то даже если данные не вводить то все равно
таблица открывается, где я только не вычищал из инспектора данные по умолчанию безполезно
клиент все равно их находит - этот момент меня напрягает

Вот на всякий случай кому интересно, листинг сервера и клиента:
1
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.01.2015, 23:54
Ответы с готовыми решениями:

Делегаты. Ликбез
Объясните пожалуйста или посоветуйте какие нибудь источники объясняющие что такое делегаты, как и с...

Ликбез по ООП
Доброго времени суток! Друзья, подскажите, пожалуйста новичку. Чем руководствоваться при создании...

Требуется ЛикБез ^,.,^
Лирическое отступление (кому неинтересно может пропустить): сломался калькулятор, починке он...

Qthread (ликбез)
Задача: 20 детей едят из одной миски, в которой 100 слив, когда ребенок хочет кушать, он берёт из...

30
9 / 9 / 4
Регистрация: 11.07.2012
Сообщений: 200
30.01.2015, 23:55  [ТС] 2
сервер

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
    unit ServerMethodsUnit1;
 
interface
 
uses System.SysUtils, System.Classes, System.Json,
    Datasnap.DSServer, Datasnap.DSAuth, DataSnap.DSProviderDataModuleAdapter,
  Data.DBXFirebird, Data.FMTBcd, Data.DB, Data.SqlExpr, Datasnap.Provider;
 
type
  TServerMethods1 = class(TDSServerModule)
    BitbaseConnection: TSQLConnection;
    ClientsTable: TSQLDataSet;
    SQLQuery1: TSQLQuery;
    procedure DSServerModuleCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    function EchoString(Value: string): string;
    function ReverseString(Value: string): string;
    Function ClientsDataSet:TDataSet; //новый метод сервера
    Procedure ClientInsert(C_SURNAME,C_NAME,C_PATRON :String); //метод добавления новой записи
    Procedure ClientUpdate(ID :Integer; C_SURNAME,C_NAME,C_PATRON :String);
    Procedure ClientDelet(ID :Integer);
    Procedure ClientFind(Qsql :String);
    Procedure ClientSelect(Qsql :String);
  end;
 
implementation
 
{%CLASSGROUP 'FMX.Controls.TControl'}
 
{$R *.dfm}
 
 
uses System.StrUtils;
 
procedure TServerMethods1.DSServerModuleCreate(Sender: TObject);
begin
  SQLQuery1.SqlConnection:=BitbaseConnection;
end;
 
function TServerMethods1.EchoString(Value: string): string;
begin
  Result := Value;
end;
 
function TServerMethods1.ReverseString(Value: string): string;
begin
  Result := System.StrUtils.ReverseString(Value);
end;
 
Function TServerMethods1.ClientsDataSet: TDataSet;
begin
  ClientsTable.Open;
  Result:=ClientsTable;
end;
 
Procedure TServerMethods1.ClientInsert(C_SURNAME,C_NAME,C_PATRON: String);
begin
 
  with SQLQuery1 do
   begin
     Close;
     SQL.Clear;
     SQL.Add('INSERT INTO CLIENTS');
     SQL.Add('(C_SURNAME,C_NAME,C_PATRON) VALUES (:C_SURNAME,:C_NAME,:C_PATRON)');
     Params[0].Value:= C_SURNAME;
     Params[1].Value:= C_NAME;
     Params[2].Value:= C_PATRON;
     ExecSQL();
   end;
 
end;
 
Procedure TServerMethods1.ClientUpdate(ID :Integer; C_SURNAME,C_NAME,C_PATRON :String);
begin
 
  with SQLQuery1 do
   begin
     Close;
     SQL.Clear;
     SQL.Add('UPDATE CLIENTS SET');
     SQL.Add('C_SURNAME = (:C_SURNAME),C_NAME = (:C_NAME),C_PATRON = (:C_PATRON) WHERE ID =(:ID)');
     Params[0].Value:= C_SURNAME;
     Params[1].Value:= C_NAME;
     Params[2].Value:= C_PATRON;
     Params[3].Value:= ID;
     ExecSQL();
   end;
 
end;
 
Procedure TServerMethods1.ClientDelet(ID :Integer);
begin
 
  with SQLQuery1 do
  begin
     Close;
     SQL.Clear;
     SQL.Add('DELETE FROM CLIENTS WHERE ID =(:ID)');
     Params[0].Value:= ID;
     ExecSQL();
  end;
 
end;
 
Procedure TServerMethods1.ClientFind(Qsql :String);
begin
 
  with SQLQuery1 do
  begin
     Close;
     SQL.Clear;
     SQL.Add('SELECT * FROM CLIENTS WHERE C_NAME = (:Qsql)');
     Params[0].Value:= Qsql;
     Open;
  end;
 
end;
 
Procedure TServerMethods1.ClientSelect(Qsql :String);
begin
 
  with SQLQuery1 do
  begin
     Close;
     SQL.Clear;
     SQL.Add(':Qsql');
     Params[0].Value:= Qsql;
     Open;
  end;
 
end;
 
 
end.
клиент

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
     unit DMclient;
 
interface
 
uses
  System.SysUtils, System.Classes, Data.DBXDataSnap, IPPeerClient,
  Data.DBXCommon, Data.DB, Data.SqlExpr, Data.FMTBcd, Datasnap.Provider,
  Datasnap.DBClient, Datasnap.DSConnect;
 
type
  TDataModule2 = class(TDataModule)
    SQLConnection1: TSQLConnection;
    SqlServerMethod1: TSqlServerMethod;
    ClientDataSet1: TClientDataSet;
    DataSource1: TDataSource;
    SqlServerMethod2: TSqlServerMethod;
    SqlServerMethod3: TSqlServerMethod;
    SqlServerMethod4: TSqlServerMethod;
    SqlServerMethod5: TSqlServerMethod;
    DataSetProvider1: TDataSetProvider;
    SqlServerMethod6: TSqlServerMethod;
    procedure DataModuleCreate(Sender: TObject);
 
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  DataModule2: TDataModule2;
 
implementation
 
{%CLASSGROUP 'Vcl.Controls.TControl'}
 
uses GFclient;
 
{$R *.dfm}
 
procedure TDataModule2.DataModuleCreate(Sender: TObject);
begin
   //SQLConnection1.Open;
   //ClientDataSet1.Open;
end;
 
end.
 
 
unit GFclient;
 
interface
 
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Grids, Vcl.DBGrids,
  Vcl.ExtCtrls, Vcl.DBCtrls;
 
type
  TForm1 = class(TForm)
    Label1: TLabel;
    Edit1: TEdit;
    DBGrid1: TDBGrid;
    BAdd: TButton;
    BApply: TButton;
    BDel: TButton;
    BEdit: TButton;
    PanelEdit: TPanel;
    EditFam: TEdit;
    EditName: TEdit;
    EditPatron: TEdit;
    LabelFam: TLabel;
    LabelName: TLabel;
    LabelPatron: TLabel;
    BCancelEdit: TButton;
    BFound: TButton;
    PanelFind: TPanel;
    BFind: TButton;
    CheckBoxFam: TCheckBox;
    BCancelFind: TButton;
    FindName: TEdit;
    CheckBoxName: TCheckBox;
    FindPatron: TEdit;
    CheckBoxPatron: TCheckBox;
    FindFam: TEdit;
    BExit: TButton;
    Label2: TLabel;
    PanelSetting: TPanel;
    LabelIP: TLabel;
    BConnect: TButton;
    ComboBoxSetIP: TComboBox;
    LabelPort: TLabel;
    EPort: TEdit;
    LabelLogin: TLabel;
    LabelPassword: TLabel;
    ELogin: TEdit;
    EPass: TEdit;
    ComboBoxSetProtocol: TComboBox;
    LabelProtocol: TLabel;
    procedure Edit1Change(Sender: TObject);
    procedure BAddClick(Sender: TObject);
    procedure BApplyClick(Sender: TObject);
    procedure BEditClick(Sender: TObject);
    procedure BCancelEditClick(Sender: TObject);
    procedure BDelClick(Sender: TObject);
    procedure BFoundClick(Sender: TObject);
    procedure BFindClick(Sender: TObject);
    procedure BCancelFindClick(Sender: TObject);
    procedure BExitClick(Sender: TObject);
    procedure CheckBoxFamClick(Sender: TObject);
    procedure CheckBoxNameClick(Sender: TObject);
    procedure CheckBoxPatronClick(Sender: TObject);
    procedure BConnectClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    FNew: Boolean;
  public
 
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
uses MethodsClient, DMclient;
 
 
procedure TForm1.FormCreate(Sender: TObject);
begin
    ComboBoxSetIP.AddItem('localhost',nil);
    ComboBoxSetIP.AddItem('192.168.0.',nil);
    ComboBoxSetIP.AddItem('192.168.1.',nil);
    ComboBoxSetProtocol.AddItem('tcp/ip',nil);
    ComboBoxSetProtocol.AddItem('http',nil);
end;
 
procedure TForm1.BConnectClick(Sender: TObject);
 
begin
 
  
   DataModule2.SqlServerMethod6.Params.ParamByName('Qsql').Value:= 'SELECT * FROM CLIENTS';
 
   if DataModule2.SQLConnection1.Connected then
   begin
      //Закрыть соединение
      DataModule2.ClientDataSet1.Close;
      DataModule2.SQLConnection1.Close;
      BConnect.Caption:='Подключиться';
      ComboBoxSetIP.Enabled:=True;
      ComboBoxSetIP.Color:=clWindow;
      ComboBoxSetProtocol.Enabled:=True;
      ComboBoxSetProtocol.Color:=clWindow;
      ELogin.Enabled:=True;
      ELogin.Color:=clWindow;
      EPass.Enabled:=True;
      EPass.Color:=clWindow;
      EPort.Enabled:=True;
      EPort.Color:=clWindow;
   end
         else
   begin
      //устанавливаем параметры подключения
      with DataModule2.SQLConnection1 do
      begin
      //Params.Values['DriverUnit']:= 'Data.DBXDataSnap';
      Params.Values['CommunicationProtocol']:= ComboBoxSetProtocol.Text;
      Params.Values['HostName']:= ComboBoxSetIP.Text;
      Params.Values['Port']:= EPort.Text;
      //Params.Values['DatasnapContext']:= 'datasnap/';
      //Params.Values['Password']:= EPass.Text;
      //имя пользователя
      //Params.Values['DSAuthUser']:=ELogin.Text;
      //пароль
      //Params.Values['DSAuthPassword']:=EPass.Text;
      //пробуем подключиться
      //Params.SaveToFile('C:\1.txt');
      Open;
      end;
 
      Label2.Caption:=DataModule2.SQLConnection1.Params.Values['HostName'];
 
      if DataModule2.SQLConnection1.Connected then
      begin
      DataModule2.ClientDataSet1.Open;
      BConnect.Caption:='Отключиться';
      ComboBoxSetIP.Enabled:=False;
      ComboBoxSetIP.Color:=clSilver;
      ComboBoxSetProtocol.Enabled:=False;
      ComboBoxSetProtocol.Color:=clSilver;
      ELogin.Enabled:=False;
      ELogin.Color:=clSilver;
      EPass.Enabled:=False;
      EPass.Color:=clSilver;
      EPort.Enabled:=False;
      EPort.Color:=clSilver;
      end;
   end;
 
end;
 
//--------------------------------------------------------------------------
 
procedure TForm1.BAddClick(Sender: TObject);
begin
    FNew:=True;
    PanelEdit.Visible:=True;
end;
 
procedure TForm1.BEditClick(Sender: TObject);
begin
    FNew:=False;
    EditFam.Text:=DataModule2.ClientDataSet1.FieldByName('C_SURNAME').AsString;
    EditName.Text:=DataModule2.ClientDataSet1.FieldByName('C_NAME').AsString;
    EditPatron.Text:=DataModule2.ClientDataSet1.FieldByName('C_PATRON').AsString;
    PanelEdit.Visible:=True;
end;
 
procedure TForm1.BDelClick(Sender: TObject);
begin
    DataModule2.SqlServerMethod3.Params.ParamByName('ID').Value:=
    DataModule2.ClientDataSet1.FieldByName('ID').AsInteger;
    DataModule2.SqlServerMethod3.ExecuteMethod;
    DataModule2.ClientDataSet1.Close;
    DataModule2.SQLConnection1.Close;
    DataModule2.SQLConnection1.Open;
    DataModule2.ClientDataSet1.Open;
end;
 
procedure TForm1.BFoundClick(Sender: TObject);
begin
   CheckBoxFam.Checked:=False;
   FindFam.Enabled:= False;
   FindFam.Color:=clSilver;
   FindFam.Text:='';
 
   CheckBoxName.Checked:=False;
   FindName.Enabled:= False;
   FindName.Color:=clSilver;
   FindName.Text:='';
 
   CheckBoxPatron.Checked:=False;
   FindPatron.Enabled:= False;
   FindPatron.Color:=clSilver;
   FindPatron.Text:='';
 
   PanelFind.Visible:=True;
end;
 
procedure TForm1.BExitClick(Sender: TObject);
begin
  Form1.Close;
end;
 
//--------------------------------------------------------------------------
 
procedure TForm1.BApplyClick(Sender: TObject);
begin
    if FNew = True then
    begin
    DataModule2.SqlServerMethod2.Params.ParamByName('C_SURNAME').Value:=EditFam.Text;
    DataModule2.SqlServerMethod2.Params.ParamByName('C_NAME').Value:=EditName.Text;
    DataModule2.SqlServerMethod2.Params.ParamByName('C_PATRON').Value:=EditPatron.Text;
    DataModule2.SqlServerMethod2.ExecuteMethod;
    end
        else
    begin
    DataModule2.SqlServerMethod4.Params.ParamByName('ID').Value:=
    DataModule2.ClientDataSet1.FieldByName('ID').AsInteger;
    DataModule2.SqlServerMethod4.Params.ParamByName('C_SURNAME').Value:=EditFam.Text;
    DataModule2.SqlServerMethod4.Params.ParamByName('C_NAME').Value:=EditName.Text;
    DataModule2.SqlServerMethod4.Params.ParamByName('C_PATRON').Value:=EditPatron.Text;
    DataModule2.SqlServerMethod4.ExecuteMethod;
    end;
 
    //DataModule2.ClientDataSet1.ApplyUpdates(0);
    PanelEdit.Visible:=False;
    DataModule2.ClientDataSet1.Close;
    DataModule2.SQLConnection1.Close;
    DataModule2.SQLConnection1.Open;
    DataModule2.ClientDataSet1.Open;
 
 
end;
 
procedure TForm1.BCancelEditClick(Sender: TObject);
begin
   PanelEdit.Visible:=False;
end;
 
//--------------------------------------------------------------------------
 
procedure TForm1.BFindClick(Sender: TObject);
var   s :string;
      n :integer;
 
begin
 
  {s:='';
  n:=0;
 
  if  FindFam.Text<>'' then
  begin
   s:=s+'C_SURNAME LIKE ''%'+FindFam.Text+'%''';
   inc(n);
  end;
 
  if  FindName.Text<>'' then
  begin
   if n>0 then s:=s+' AND ';
   s:=s+'C_NAME LIKE ''%'+FindName.Text+'%''';
   inc(n);
  end;
 
  if  FindPatron.Text<>'' then
  begin
   if n>0 then s:=s+' AND ';
   s:=s+'C_PATRON LIKE ''%'+FindPatron.Text+'%''';
   inc(n);
  end;
 
 
  if n>0 then
  begin   }
  //s:='SELECT * FROM CLIENTS WHERE '+s;
  //label2.Caption:=s;
  s:=DataModule2.ClientDataSet1.FieldByName('C_NAME').AsString;
  s:='"'+s+'"';
  label2.Caption:=s;
  DataModule2.SqlServerMethod5.Params.ParamByName('Qsql').Value:=s;
  DataModule2.SqlServerMethod5.ExecuteMethod;
  DataModule2.ClientDataSet1.Close;
  DataModule2.SQLConnection1.Close;
  DataModule2.SQLConnection1.Open;
  DataModule2.ClientDataSet1.Open;
  //end;
 
  {DataModule2.ClientDataSet1.Close;
  DataModule2.ClientDataSet1.CommandText:= 'SELECT * FROM CLIENTS WHERE C_NAME = "Денис"';
  DataModule2.ClientDataSet1.Open; }
 
 
 
end;
 
procedure TForm1.BCancelFindClick(Sender: TObject);
begin
   PanelFind.Visible:=False;
end;
 
procedure TForm1.CheckBoxFamClick(Sender: TObject);
begin
   if FindFam.Enabled = False then
   begin
   FindFam.Enabled:= True;
   FindFam.Color:=clWindow;
   end
                              else
   begin
   FindFam.Enabled:= False;
   FindFam.Color:=clSilver;
   end;
   FindFam.Text:='';
end;
 
procedure TForm1.CheckBoxNameClick(Sender: TObject);
begin
   if FindName.Enabled = False then
   begin
   FindName.Enabled:= True;
   FindName.Color:=clWindow;
   end
                              else
   begin
   FindName.Enabled:= False;
   FindName.Color:=clSilver;
   end;
   FindName.Text:='';
end;
 
procedure TForm1.CheckBoxPatronClick(Sender: TObject);
begin
   if FindPatron.Enabled = False then
   begin
   FindPatron.Enabled:= True;
   FindPatron.Color:=clWindow;
   end
                              else
   begin
   FindPatron.Enabled:= False;
   FindPatron.Color:=clSilver;
   end;
   FindPatron.Text:='';
end;
 
//--------------------------------------------------------------------------
 
procedure TForm1.Edit1Change(Sender: TObject);
var SMC:TServerMethods1Client;
begin
 
    SMC:=TServerMethods1Client.Create(DataModule2.SQLConnection1.DBXConnection);
    try
       Label1.Caption:=SMC.EchoString(Edit1.Text);
    finally
       SMC.Free;
    end;
 
end;
 
 
 
 
end.
0
9 / 9 / 4
Регистрация: 11.07.2012
Сообщений: 200
03.02.2015, 23:12  [ТС] 3
После "глубокого" анализа кажется я нащупал причину многих своих бед.

Все дело в том, что провайдер на стороне клиента DataSetProvider1 (через который собственно данные в
итоге отображаются в DBGrid1) настроен (через инспектор) на работу с моим первым серверным методом
SqlServerMethod1.
А там у нас, что:

Delphi
1
2
3
4
5
   Function TServerMethods1.ClientsDataSet: TDataSet;
begin
  ClientsTable.Open;
  Result:=ClientsTable;
end;
правильно, у SQLDataSet свойство CommandType задано ctTable,
а свойство Commandtext содержит название таблицы - поэтому при подключении
собственно она и отображается. Когда я делаю вставку/удаление или редактирование
которые работают через SqlServerMethod2/SqlServerMethod3 и SqlServerMethod4 соответственно,
то увижу я как данные изменились - только переподлключив ТSQLconnection ведь все
остальные методы не связаны с провайдером DataSetProvider1

Вывод - надо, что нибудь умное написать вместо:

Delphi
1
2
  ClientsTable.Open;
  Result:=ClientsTable;
например вместо ctTable выбрать ctQuery , и написать что то вроде этого
(для начала, потом можно и параметр из клиента подсовывать):

Delphi
1
2
3
4
5
6
7
  Function TServerMethods1.ClientsDataSet: TDataSet;
begin
  ClientsTable.Close;
  ClientsTable.CommandText := 'select * from CLIENTS';
  ClientsTable.Open;
  Result:=ClientsTable;
end;
Помогите мне это написать (пока не получается ругается на запрос)
0
9 / 9 / 4
Регистрация: 11.07.2012
Сообщений: 200
09.02.2015, 22:02  [ТС] 4
С запросом все в порядке - разобрался. Кавычки были не те, у меня было "Денис" , а надо
кто бы мог подумать ' 'Денис' ' (хотя в другом проекте и первый синтаксис прокатывал).

Вообщем сам по себе запрос SELLECT срабатывает:

на сервере у компонента ClientsTable (это SQLDataset) свойство
CommandType:= stQuery
CommandText:= select * from CLIENT


Delphi
1
2
3
4
5
6
7
  Function TServerMethods1.ClientsDataSet: TDataSet;
begin
  ClientsTable.Close;
  ClientsTable.CommandText := 'select * from CLIENTS WHERE C_NAME = ''Денис''';
  ClientsTable.Open;
  Result:=ClientsTable;
end;
Таким образом я нажимаю кнопку "Подключить" и у меня в гриде отображается как и задумывалось не
вся таблица а только одна строчка - SELECT работает.

Хорошо думаю давай сделаю так:

сервер

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
    Function TServerMethods1.ClientsDataSet: TDataSet;
begin
  ClientsTable.Open;
  Result:=ClientsTable;
end;
 
Procedure TServerMethods1.ClientFind(Qsql :String);
begin
  ClientsTable.Close;
  ClientsTable.CommandText := 'select * from CLIENTS WHERE C_NAME = (:Qsql)';
  ClientsTable.Params[0].Value:= Qsql;
end;

клиент

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
procedure TForm1.BFindClick(Sender: TObject);
var   s :string;
      
begin
 
  s:=DataModule2.ClientDataSet1.FieldByName('C_NAME').AsString;
  s:=''''+s+''''; //воооотакие кавычки ему видите ли нравятся :) 
  DataModule2.SqlServerMethod5.Params.ParamByName('Qsql').Value:=s;
  DataModule2.SqlServerMethod5.ExecuteMethod;
  DataModule2.SqlServerMethod1.ExecuteMethod;
  //DataModule2.ClientDataSet1.ApplyUpdates(0);
  DataModule2.ClientDataSet1.Close;
  DataModule2.ClientDataSet1.Open;
  
end;
итогом после нажатия "найти" открывается пустая таблица - т.е. ClientDataSet1 пуст после открытия
а если переподключить ТSQLconnection то будет тот набор данных который я задавал раньше в инспекторе
(CommandText:= select * from CLIENT)

метод DataModule2.ClientDataSet1.ApplyUpdates(0); - тупо нечего не дает, он работает только когда есть
связка компонентов: DSProviderConnection1-DataSetProvider1 соответственно клиент-сервер.

ОБЪЯСНИТЕ МНЕ НЕДАЛЕКОМУ - ЕСЛИ Я ДЕЛАЮ ПРОЕКТ НЕ НА ОСНОВЕ IappServer
А ИСПОЛЬЗУЯ НОВЫЕ КОМПОНЕНТЫ DELPHI 2010 И СТАРШЕ Я ГОВОРЮ О SqlServerMethod
МЕТОДЫ КОТОРОГО "ЗЕРКАЛИРУЮТСЯ" С МЕТОДАМИ СЕРВЕРА И МОДИФИЦИРУЮТ ДАННЫЕ ЭТО ФАКТ

Я НЕ ВЕРЮ, ЧТО НЕТ СПОСОБА ОБНОВИТЬ НА КЛИЕНТЕ ClientDataSet1 И ПРИ ЭТОМ НЕ РВАТЬ СОЕДИНЕНИЕ

ПОЧЕМУ ПОСЛЕ

Delphi
1
2
  DataModule2.ClientDataSet1.Close;
  DataModule2.ClientDataSet1.Open;
ClientDataSet1 пуст ? Ведь ТSQLconnection все также подключен к datasnap, а провайдер все также настроен на
SqlServerMethod1 который

Delphi
1
2
  ClientsTable.Open;
  Result:=ClientsTable;
возвращает нам набор данных с сервера

по всей логике
1 Передали через параметр данные ' 'Денис' '
DataModule2.SqlServerMethod5.Params.ParamByName('Qsql').Value:=s;

2 Применили метод DataModule2.SqlServerMethod5.ExecuteMethod;

3 На сервере в это время изменился CommandText у ClientsTable
был (select * from CLIENT) стал ('select * from CLIENTS WHERE C_NAME = ''Денис''')

Delphi
1
2
      ClientsTable.CommandText := 'select * from CLIENTS WHERE C_NAME = (:Qsql)';
      ClientsTable.Params[0].Value:= Qsql;
4 Применили метод DataModule2.SqlServerMethod1.ExecuteMethod;
а этот метод в отличии от DataModule2.SqlServerMethod5 уже связан с провайдером
DataSetProvider1 на который в свою очередь настроен наш несчастный ClientDataSet1 - DBGrid

5 как только применили - на сервере обновился ClientsTable (это SQLDataset)

Delphi
1
2
        ClientsTable.Open;
        Result:=ClientsTable;
6 Вот только после DataModule2.ClientDataSet1.Open; назад с сервера ничего не вернулось
все включено, все компоненты друг с другом связаны и работают . Метод тестовый "эхо" с сервера
работает - значит связь есть, а вот ClientDataSet1 - ПУСТОЙ (ПУСТАЯ ТАБЛИЦА) И ВСЕ

Ну ведь пишут же люди проекты на datasnap, по форумам видно, да и компонент SqlServerMethod
тоже же не просто так придумали "побаловатся" ответь те кто нибудь на этот вопрос и
на вопрос какие библиотеки нужны на клиенте (клиент у меня без установленной delphi не работает)
0
9 / 9 / 4
Регистрация: 11.07.2012
Сообщений: 200
12.02.2015, 09:27  [ТС] 5
Хм, вероятно термины:
"дискуссия","диалог","обсуждение","мозговой штурм","взгляд со стороны","свежее мнение","под другим углом зрения"
Можно смело заменить всего одним:
"монолог"
0
9 / 9 / 4
Регистрация: 11.07.2012
Сообщений: 200
16.02.2015, 17:51  [ТС] 6
Теперь понятно, почему все так "ТУХЛО"

Скачал переведенный на русский язык мануал:

Delphi 2010 DataSnap:
новые возможности в управлении
и доступе к данным
Боб Сворт (Bob Swart), Bob Swart Training & Consultancy (eBob42)
Октябрь 2009 г.


Обрадовался, блин - как же целая книга по современному datasnap (теперь узнаю "who is who")
не жалкая статейка от васи пупкина, а целый труд от профессора Боба Сварта, уж он то точно "сечет"
как эта "хня" работает.

НА ДЕЛЕ ВСЕ ТЕ СТАТЕЙКИ ОТ ВАСЕЙ ПУПКИНЫХ ИЗ ИНЕТА - НЕ ЧТО ИНОЕ КАК ВЫБОРОЧНАЯ НАРЕЗКА ГЛАВ
С ЭТОЙ КНИЖКИ


нет не спорю удобно когда когда все в одном месте и даже чуть чуть чуть подробнее - но инфа та же
нового с грамм

Боб Сварт - сам себе противоречит: с одной стороны - новый datasnap он почему новый, он новый потому
что мы уходим от COM зависимости для этого используем новые компоненты - SqlServerMethod которых
раньше просто не было и не используем старые компоненты - DSProviderConnection которые раньше были
а сейчас их оставили только для совметимости со старыми серверами datasnap (чтобы новый клиент можно
было подключить к старому серверу)
повторяю б..ь чисто для совместимости т.е если мы новый проект пишем - все не используем мы - DSProviderConnection

НУ И ЧЕ Сварт делает (а за ним как теперь понятно повторяют в своих обзорах все Васи Попугайкины)
когда надо данные для чтения отобразить - то это новый модный - SqlServerMethod
а как дело дошло до чего то ближе к жизни то
утверждение - что SqlServerMethod изменить данные не способен (не способен видимо только по тому,
что Боб просто сам тупо не понял как это сделать) , а вот Осипов не утверждает что не способен
когда дело дошло до правки он как Боб тут же не сливает с формы компонент SqlServerMethod
заменяя его на DSProviderConnection (тем самым реализуя старый классический IappServer) он
демонстрирует метод новой вставки только на основе SqlServerMethod - то что это работает это факт
проверенно мной лично

А самая большая беда, что у Осипова datasnap посвящен только небольшой раздел где он вскольз
только один insert и проиллюстрировал и контактов ни каких у автора в интернете нет (в смысле
email) - хоть в письме бы спросить можно было

Вот нах...на делать уход от COM вводить SqlServerMethod - если не один полноценный рабочий проект,
таким образом все равно создать нельзя - это если верить в правоту Сварта ?

у этого деятеля еще один труд есть по современней

Delphi / RAD Studio
DataSnap XE2
Development
Essentials
Dr.Bob’s Delphi XE2 DataSnap Development Essentials
Second XE2 Edition, April 2012for customers of Bob Swart

Почитать пока не пришлось - но сдается такими темпами там тоже мало интересного...
2
0 / 0 / 0
Регистрация: 22.10.2013
Сообщений: 5
02.05.2015, 15:45 7
отличная тема и рассуждения, разобрался с многими своими недочетами и ошибками, полезно
0
16 / 16 / 1
Регистрация: 29.11.2014
Сообщений: 227
24.07.2015, 00:27 8
Привет, kebot! Спасибо тебе за ту тему! Тоже сейчас разбираюсь с этим вопросом.
Подскажи - доделал ли ты свой проект? И реально ли в этой технологии использовать в качестве тонкого клиента веб-браузер? Как здесь?
http://teran.karelia.pro/articles/item_6113.html
0
9 / 9 / 4
Регистрация: 11.07.2012
Сообщений: 200
06.08.2015, 19:47  [ТС] 9
Привет GringoV,
на базовом уровне у меня проект давно работает. Сейчас занят выполнением конкретно заказа (на datasnap).
Эту статью я раньше тоже читал, чуть ли не единственный "нормальный" практический пример по REST.
У самого в планах освоить REST причем очень бы хотелось, чтобы крутился на серваке один сервер приложений,
а тонкие клиенты были разные
1 windows приложение
2 web клиент
3 android приложение
4 ios приложение
вот тогда бы был "он клюзив"
сейчас нет времени ковырять, REST пока хоть бы на классическом DS законченное рабочее приложение сделать

но серверные методы я для манипуляциями наборами данных (запросы) не использую - слишком муторно
для каждого конкретного случая создавать метод, останавливать службу, зеркалировать метод, запускать службу,
прописывать параметры, обновлять список параметров и тд итп.
все это заменяет простая комбинация ну к примеру

Delphi
1
2
3
    DataModule2.ClientDataSet10.Close;
    DataModule2.ClientDataSet10.CommandText:='select MAX(PR_KEY) AS "Max Key" from PLAN_RECRUT';
    DataModule2.ClientDataSet10.Open;
и все одна строка запроса, а провайдеры сделают все остальное

методы я тоже использую но для таких вещей, как например передача картинки в blob поле
здесь на форуме у меня несколько тем было (тоже в вопросе разобрался только на половину)

GringoV если сделаешь web клиент скинь пример пожалуйста, больше всего мне интересно,
для этого сервер datasnap нужно с помощью мастера с нуля создавать выбирая rest,
или же можно в уже рабочий "классический" проект - добавить web модуль ?
0
16 / 16 / 1
Регистрация: 29.11.2014
Сообщений: 227
06.08.2015, 20:07 10
Я понял тебя! Спасибо за такой развёрнутый ответ. Что хотел сказать, я в процессе освоения этой технологии, но есть цель - написать пробное веб-приложение.

По поводу серверных методов - частично с тобой согласен, но мне кажется мы ещё не всё "вкурили". Я могу ошибаться, но не все запросы корректно отрабатывают с клиента. Сегодня экспериментировал с транзакциями на MySQL, так вот одна и та же хранимая процедура из mysql.exe сохранялась и отрабатывала на ура, а когда запрос слал из workbehch на создание такой же процедуры под другим именем - хрен)) Привожу кусок из кода для отката при ошибке на сервере.
SQL
1
2
3
4
5
DECLARE exit handler FOR sqlexception
BEGIN
ROLLBACK;
SELECT 'this is error';
END;
спотыкалось на rollback...

На данный момент тестирую технологию DATASNAP - отпишусь по этому вопросу.

Да, также наткнулся на UNIGUI - это конечно другая песня, но потестил - вещь классная для разработки веб-приложений из под Delphi.
0
16 / 16 / 1
Регистрация: 29.11.2014
Сообщений: 227
28.08.2015, 02:04 11
Привет Kebot! Как продвигается твой заказ на DataSnap? У меня был небольшой перерыв с этой технологией, но сейчас я снова вернулся, экспериментирую.

По твоим стопам прочитал Д. Осипова - для начала - очень ценная книга по данной технологии;

Базовые вещи (вставка, удаление, редактирование) научился делать 2 способами
-через методы сервера
Delphi
1
Clientdatamoduleunit.ClientDataModule.SqlServerMethod2.ExecuteMethod;
-через создание переменной зазеркаленных серверных методов
Delphi
1
2
3
SMC:=TServerMethods1Client.Create(Clientdatamoduleunit.ClientDataModule.SQLConnection1.DBXConnection);
SMC.insertRecord;
SMC.Free;
Также попробовал твой способ слать запросы прямиком из клиента из Clientdataset, но получил ошибку, может что-то не так делаю...
На кнопку, в клиенте повесил следующий код...
Delphi
1
2
3
ClientDataModule.ClientDataSet1.Close;
    ClientDataModule.ClientDataSet1.CommandText:='select*from test_db';
    ClientDataModule.ClientDataSet1.Open;
Скриншот ошибки
Ликбез по DataSnap


Подскажи как делал ты? В чем я ошибся?

Также попробовал менять схему получения данных, предложенную Осиповым...
Пробовал через создание 2 SQLDataSet - одно множество на сервере, другое на клиенте, и присваивать... но система генерит ошибку
Delphi
1
2
SMC:=TServerMethods1Client.Create(Clientdatamoduleunit.ClientDataModule.SQLConnection1.DBXConnection);
Clientdatamoduleunit.ClientDataModule.SQLDataSet1.Assign(SMC.MySQLDataSet);
скриншот ошибки...
Ликбез по DataSnap


Подскажи, не нашёл ли ты ещё каких-то фишек, упрощающих труды программистов))) А то мне кажется схема, предложенная Осиповым слишком длинная, или я привык к SQLConnection - SimpleDataSet - DataSource - DataControl )))

Добавлено через 3 минуты
Также подскажи - делал ли ты личный кабинет по данной технологии? Если да, то как решал вопрос с авторизацией? Я, насколько понял, в DataSnap есть более менее готовое решение? Или я ошибаюсь?

Добавлено через 1 час 20 минут
У меня ещё такой вопрос - ты когда методы новые создаешь, ты каждый раз под них на стороне клиента создаешь sqlServerMethod?
Скажем у нас 30 методов - это 30 компонент создавать? )))
Или всё же динамически компонент используешь? Когда метод нужен подгружаешь в него ? Но тогда его и динамически создавать и уничтожать надо, я так понимаю.

Добавлено через 43 минуты
И про транзакции - есть ли они в DataSnap и нужны ли они? Ведь как таковой сервер приложений не хранит данные...
0
9 / 9 / 4
Регистрация: 11.07.2012
Сообщений: 200
31.08.2015, 07:01  [ТС] 12
И тебе привет,

У меня ещё такой вопрос - ты когда методы новые создаешь, ты каждый раз под них на стороне клиента создаешь sqlServerMethod
В том то и дело - если через методы действовать то конструкция получается предельно жесткая.
Само действие выполняет метод на сервере, в случае запроса - это запрос с параметрами, например


Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    Procedure TServerMethods1.ClientUpdate(EMPLOYES_KEY,EMP_MANAGER_KEY,EMP_ISP_KEY :Integer;
                                       EMP_SURNAME,EMP_NAME,EMP_PATRON,EMP_PROF,
                                       EMP_POL,EMP_BITHDAY,EMP_RASA,EMP_TEL,EMP_EMAIL,
                                       EMP_ADRES,EMP_SOBESED_DATA,EMP_SOBESED_VAC,
                                       EMP_UNIFORMA,EMP_FOTO_F: String);
begin
 
  with SQLQuery1 do
   begin
     Close;
     SQL.Clear;
     SQL.Add('UPDATE EMPLOYES SET');
     SQL.Add('EMP_MANAGER_KEY = (:EMP_MANAGER_KEY),EMP_ISP_KEY = (:EMP_ISP_KEY),');
     SQL.Add('EMP_SURNAME = (:EMP_SURNAME),EMP_NAME = (:EMP_NAME),EMP_PATRON = (:EMP_PATRON),');
     SQL.Add('EMP_PROF = (:EMP_PROF),EMP_POL = (:EMP_POL),EMP_BITHDAY = (:EMP_BITHDAY),');
     SQL.Add('EMP_RASA = (:EMP_RASA),EMP_TEL = (:EMP_TEL),EMP_EMAIL = (:EMP_EMAIL),');
     SQL.Add('EMP_ADRES = (:EMP_ADRES),EMP_SOBESED_DATA = (:EMP_SOBESED_DATA),EMP_SOBESED_VAC = (:EMP_SOBESED_VAC),');
     SQL.Add('EMP_UNIFORMA = (:EMP_UNIFORMA),EMP_FOTO_F = (:EMP_FOTO_F) ');
     SQL.Add('WHERE EMPLOYES_KEY =(:EMPLOYES_KEY)');
     Params[0].Value:= EMP_MANAGER_KEY;
     Params[1].Value:= EMP_ISP_KEY;
     Params[2].Value:= EMP_SURNAME;
     Params[3].Value:= EMP_NAME;
     Params[4].Value:= EMP_PATRON;
     Params[5].Value:= EMP_PROF;
     Params[6].Value:= EMP_POL;
     Params[7].Value:= EMP_BITHDAY;
     Params[8].Value:= EMP_RASA;
     Params[9].Value:= EMP_TEL;
     Params[10].Value:= EMP_EMAIL;
     Params[11].Value:= EMP_ADRES;
     Params[12].Value:= EMP_SOBESED_DATA;
     Params[13].Value:= EMP_SOBESED_VAC;
     Params[14].Value:= EMP_UNIFORMA;
     Params[15].Value:= EMP_FOTO_F;
     Params[16].Value:= EMPLOYES_KEY;
     ExecSQL();
   end;
 
end;

на стороне клиента мы обращаемся к этому методу, используя компонент который в дизайнере жестко
привязали к этому методу - вообщем дико не удобно стоит чуть поменять запрос - это новый метод и новый
компонент (возможно
1 - попробовать программно подключать\отключать компонент к разным методам
2 - попробовать динамически создавать\ удалять компонент (как предложил ты)
но это все равно не решит вопроса, как обновить данные на клиенте после изменений не рвя подключение

По этим причинам я (как наверное и 99% остальных) запросы к базе делаю не через методы, а методы
использую но для других задач.

Также попробовал твой способ слать запросы прямиком из клиента из Clientdataset, но получил ошибку, может что-то не так делаю...
Да все так, только надо помнить, что:

На стороне сервера у компонента datasetprovider должно быть включено свойство poAllowCommandtText в опциях
на сервере:

sqldataset (свойство commandtype - ctqwery) - sqlqwery - datasetprovider (poAllowCommandtTex - true)

на клиенте

clientdateset( provider name - datasetprovider сервера, remoteserver - dsproviderconnection) - datasource

и все работает, у меня к базе уже наверно запросов 300 причем некоторые "трехэтажные" - собирают
данные из 5-ти таблиц + вычисляемые поля + группировки, сортировки, левые /правые соединения, склейки ...
как бы я все это через методы делал - даже думать не хочу.

Также подскажи - делал ли ты личный кабинет по данной технологии? Если да, то как решал вопрос с авторизацией? Я, насколько понял, в DataSnap есть более менее готовое решение? Или я ошибаюсь?
Готовое решение - наверняка есть, вот только мне о нем никто не рассказал все что я знаю это

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
       //устанавливаем параметры подключения
      with DataModule2.SQLConnection1 do
      begin
      Params.Clear;
      Params.Values['DriverUnit']:= 'DBXDataSnap';
      Params.Values['CommunicationProtocol']:= ComboBoxSetProtocol.Text;
      Params.Values['HostName']:= ComboBoxSetIP.Text;
      Params.Values['Port']:= ComboBoxSetPort.Text;
      Params.Values['Filters'] :='{}//';  //набор фильтров
      //Params.Values['DatasnapContext']:= 'datasnap/';
      //Params.Values['DSAuthUser']:=ELogin.Text;  //имя пользователя
      //Params.Values['DSAuthPassword']:=EPass.Text;  //пароль
      Open; //пробуем подключиться
      end;
если у sqlconnection свойство loginprompt сделать true то вылазит "готовое решение" но мне хотелось бы
как то это все в своем окошке со своими параметрами, дизайном и так далее - сделать

Может я поступил не правильно ( не считаю себя пока настоящим программистом - максимум любитель)
но я сделал так


1- нарисовал свою форму авторизации
2- в базе данных в табличке пользователей создал поля логин и пароль (занес данные)

при запуске программа подключается к серверу приложений без всяких паролей но для
пользователя вылазит только окошко авторизации в модальном режиме
дальше дело техники если - пользователь правильно данные ввел то происходит
как бы "подключение" else нажатием на кнопку "выход" он сам рвет соединение

как то так, пока меня устраивает может в будущем найду подводные камни...

Про транзакции - сам дуб дубом - если в двух словах


P/S по web клиенту если что найдешь присылай - реально интересно
0
16 / 16 / 1
Регистрация: 29.11.2014
Сообщений: 227
31.08.2015, 13:19 13
Привет, kebot! Спасибо за такой развернутый ответ. Никак не могу сделать Select через провайдеры, вроде подключил все по книжке, выставил в DataSetProvider в Options poAllowCommandText, теперь получаю - другую ошибку - не может видите ли select выполнить на открытом множестве (на sqldataset или аналогично на sqlquery на сервере) - оно и понятно, что не может, но как его отключить перед селектом и включить после... непонятно... - запрос то идет из клиента, а в серверных методах на клиенте нет доступа к компонентам сервера... в общем я пока в думах))
Хотел у тебя спросить - ты встречал такую ошибку?
Ликбез по DataSnap
0
9 / 9 / 4
Регистрация: 11.07.2012
Сообщений: 200
31.08.2015, 14:47  [ТС] 14
На стороне сервера у компонента sqlqwery есть свойство sql
в открывшемся редакторе добавь вручную

SQL
1
SELECT * FROM твоя таблица
и посмотри на клиенте отображаются данные в dbgrid если да то смело используй код для своих запросов

Delphi
1
2
3
4
      
       DataModule2.ClientDataSet2.Close;  \\здесь вот и закрываем
       DataModule2.ClientDataSet2.CommandText:='твой запрос ';
       DataModule2.ClientDataSet2.Open;
Добавлено через 11 минут
а в серверных методах на клиенте нет доступа к компонентам сервера..
не понял фразу, какие к чертям серверные методы

у нас два провайдера настроены друг на друга = ТУНЕЛЬ

У клиентского датасет нужно выбрать провайдер сервера тот самый который связан с квери на сервере,
в этом квери (в редакторе пропиши запрос) и вот она связь

ели данные нужно обновить на клиенте после изменений - то используем метод эплиапдейт
0
16 / 16 / 1
Регистрация: 29.11.2014
Сообщений: 227
31.08.2015, 15:49 15
kebot, предыдущий пост подуставший писал, поэтому путанно получилось,
Смотри, пытаюсь работать через провайдеры таким образом...

На сервере подключил так...

Sqlconnection1 (подключаюсь к СУБД MySQL к демо БД test_db)
Sqlquery1 (в свойстве SQL прописал select*from mytable where primary_key>3)
DataSetProvider1 (poAllowCommandText в true)

либо через SqlDataSet, тоже самое...
Sqlconnection1 (подключаюсь к СУБД MySQL)
SqlDataSet1 (Commandtype:=ctquery;CommandText:=select*from mytable where primary_key>3)
DataSetProvider1Server (poAllowCommandText в true)

Вот картинка со стороны сервера...
Ликбез по DataSnap


На клиенте так...
Sqlconnection1 (Driver выставил в datasnap)
DSProviderConnection1(SQLconnection:=SqlConnection1;ServerClassName:=TServerMeth ods)
ClientDataSet1(RemoteServer:=DSProviderConnection1; ProviderName:=DataSetProvider1Server)
DataSource(DataSet:=ClientDataSet1)
Выглядит так...
Ликбез по DataSnap


В чем у меня проблема?

На кнопку вешаю такую обработку...
Delphi
1
2
3
4
5
6
7
procedure TForm2.Button3Click(Sender: TObject);
begin
 
ClientDataSet1.Close;
ClientDataSet1.CommandText:='select*from test_db';
ClientDataSet1.Open;
end;
При нажатии получаю вот такую ошибку...
Ликбез по DataSnap


То есть DataSetProvider1Server работает через SqlQuery и при попытке заменить запрос натыкается на открытое множество...
Пытаюсь понять в чем ошибся, потому что ты говоришь, что у тебя всё летает.

Также, заметил такую "байду"...
Пытаюсь делать изменения в Dbgrid "ручками"... потом жму на кнопку, в которой прописано
Delphi
1
Clientdataset1.ApplyUpdates(0); ClientDataSet1.close; ClientDataset1.open;
И изменения не сохраняются. Тоже курю в чем может быть дело)) Пробовал тестить таким образом
[DELPHI]showmessage('Updated '+inttostr(clientdataset1.ChangeCount));[DELPHI]
Заметил, что если правишь одну строку число изменений равно нулю, а если правишь 2 строки - то число изменений равно двум. Глюк?))
В реальном проекте такое врят ли понадобится, но всё же - странно что такое наблюдается.

Скажи, может быть ты ещё какие то свойства прописывал у провайдеров, чтоб они сами закрывали и открывали множество? Потому что разница в наших наборах только в том, что ты на файрберде пишешь а я на мускуле, но это не должно влиять.
0
9 / 9 / 4
Регистрация: 11.07.2012
Сообщений: 200
31.08.2015, 18:10  [ТС] 16
Попробуй запрос с клиента не ко всей базе данных сделать, а все таки к конкретной таблице
я не знаю как там на mysql но у меня запросы идут к таблицам а не к BASE.FDB в моем случае
0
16 / 16 / 1
Регистрация: 29.11.2014
Сообщений: 227
01.09.2015, 07:22 17
Короче,kebot, решение нашёл - не знаю насколько оно грамотное, но, блин, работает))) Возможно, это огород, но чего-то лучшего не нашел.
Ошибка была в том, что пытался изменить запрос на открытом множестве и как-то надо было его закрыть. Ладно, думаю, сделаю это в ручную...

-создал методы закрытия / открытия множества на сервере
-создал переменную серверного типа на клиенте
-вызвал методы с клиента для закрытия множества на сервере

Итого - как сделать Select в технологии DataSnap? (Ну и не только select, а все запросы к БД - update, delete и т.д... )

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TForm1.Button1Click(Sender: TObject);
var SMC:TServerMethods1Client;
begin
SMC:=TServerMethods1Client.Create(Sqlconnection1.DBXConnection);
 
ClientDataSet1.Close;
SMC.CloseDataSet; // метод закрытия множества на сервере - создал его в ручную
 
ClientDataSet1.CommandText:='select*from mytable where primary_key>5';
 
ClientDataSet1.Open; // метод открытия множества на сервере - создал его в ручную
SMC.OpenDataSet;
 
SMC.Free;
 
end;
Либо другой вариант...
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
procedure TForm1.Button1Click(Sender: TObject);
var SMC:TServerMethods1Client;
begin
SMC:=TServerMethods1Client.Create(Sqlconnection1.DBXConnection);
SMC.CloseDataSet;
 
//ClientDataSet1.CommandText:='Select*from mytable';
SMC.CommandText('select*from mytable where primary_key>5'); // Метод сервера...
SMC.OpenDataSet;
 
SMC.Free;
 
 
// Обновляем множество на клиенте
Clientdataset1.Close;
Clientdataset1.Open;
 
 
end;
Результат
Ликбез по DataSnap


P.S. По поводу того запроса Select*from test_db это просто моя ошибка, в mysql все работает по стандартам sql, то есть запросы к таблицам.
0
16 / 16 / 1
Регистрация: 29.11.2014
Сообщений: 227
01.09.2015, 07:30 18
Короче, kebot, твоя ветка по DataSnap развивается)))
0
16 / 16 / 1
Регистрация: 29.11.2014
Сообщений: 227
03.09.2015, 12:11 19
kebot Приветствую, я тут продолжаю экспериментировать с DataSnap, накопал аж 3 способа для Insert | Delete | Update... Чуть позже об этом напишу, ты мне вот что скажи - ранее ты писал, что у тебя было несколько компов, на которых ты экспериментировал с DataSnap, что на тех, на которых не было Delphi - ниче не работало - решил ли ты этот вопрос?
0
0 / 0 / 0
Регистрация: 04.09.2015
Сообщений: 1
04.09.2015, 16:58 20
GringoV, Привет, сам тоже как раз ковыряю DataSnap, у меня тоже была такая проблема. Решается прописыванием на клиенте в uses модуля midaslib. После чего клиент также не требует таскания с собой midas.
0
04.09.2015, 16:58
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.09.2015, 16:58
Помогаю со студенческими работами здесь

Ликбез по ТВ и apple tv
Привет, у меня несколько вопросов, которые могут показаться глупыми, но если вы развеете мои...

DataSnap и БД
Добрый день! Кто нить работал с DataSnap и БД, Нашел статью как работать и пример, сервер...

Ликбез по стеку прошу
На скрине 1 пример с известного сайта. Из того куда указывает SP заключаю, что в качестве значения...

ликбез по оконным приложениям
Здравствуйте! Вот и подходит дедлайн по курсачу, а проект застрял на стадии &quot;создал папку курсач&quot;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru