execute dynamic sql in datasnap client

老子叫甜甜 提交于 2019-12-08 06:33:57

问题


Is it possible to share database connection between datasnap server and client?

I want to execute dynamic sql in client and receive results.


回答1:


I found 2 ways to execute dynamic sql in client side

1) Using DbxConnection (dbExpress)

// Server code
function TServerMethods1.GetConnection: TDbxConnection;
begin
  Result := DBConnection.DBXConnection;
end;


//Client code
dbxConnection := ServerMethods.GetConnection;
command := dbxConnection.CreateCommand;
command.Text := 'SELECT COUNT(1) FROM clients WHERE name LIKE :name';
param := com.CreateParameter;
param.Name := 'name';
param.DataType := TDBXDataTypes.WideStringType;
param.Value.SetString('%name%');
command.Parameters.AddParameter(param);
reader := command.ExecuteQuery;
reader.Next; // to Fetch row
ShowMessage(reader.Value[0].AsString);

2) Using DataSet descendant

Server side components

ServerMethods class must be TDSServerModule descendant

  • TConnection descendant
  • TQuery descendant
  • TDataSetProvider (set poAllowCommanedText to true)

Client side components

  • TSqlConnection (for DataSnap connection)
  • TDsProviderConnection (for DataSnap server methods)
  • TClientDataSet (set provider)

code to execute query

CDS.Close; // TClientDataSet
CDS.CommandText := 'SELECT COUNT(*) FROM clients WHERE name LIKE :name';
CDS.Params.ParamByName('name').AsString := '%name%';
CDS.Open;
ShowMessage(CDS.Fields[0].AsString);

Server side code:

MainMethods.pas

TMainMethods = class(TDSServerModule)
  PgQuery: TPgQuery;
  PgQueryProvider: TDataSetProvider;
  PgConnection: TPgConnection;
end;

MainMethods.dfm

object MainMethods: TMainMethods
  Height = 248
  Width = 440
  object PgConnection: TPgConnection
    Left = 200
    Top = 32
    ...
  end
  object PgQuery: TPgQuery
    Connection: PgConnection
    Left = 32
    Top = 24
  end
  object PgQueryProvider: TDataSetProvider
    DataSet = PgQuery
    Options = [poAllowCommandText, poUseQuoteChar]
    Left = 120
    Top = 24
  end
end

Client side code:

client.pas

TVerusClient = class(TDataModule)
  dbxVerusConnection: TSQLConnection;
  dbxSqlConnectionProvider: TDSProviderConnection;
  cdsSqlDataSet: TClientDataSet;
end;

client.dfm

object VerusClient: TVerusClient
  Height = 271
  Width = 415
  object dbxVerusConnection: TSQLConnection
    DriverName = 'DataSnap'
    LoginPrompt = False
    ...
  end
  object dbxSqlConnectionProvider: TDSProviderConnection
    ServerClassName = 'TMainMethods'
    SQLConnection = dbxVerusConnection
    Left = 176
    Top = 32
  end
  object cdsSqlDataSet: TClientDataSet
    ProviderName = 'PgQueryProvider'
    RemoteServer = dbxSqlConnectionProvider
    Left = 176
    Top = 104
  end
end



回答2:


Main goal for DataSnap(Multi-Tier) application is security.You cannot share objects(connections,resources) directly(native) in remote mode but You can change SQL of Datasets on Session . but it is not secure.

// Server Code
procedure TMyServerMethod.ChangeSQL(ASQL:string); // insecure
begin
  AdoQuery1.Active:=false;
  AdoQuery1.SQL.Text:=ASQL; // AdoQuery,DbxExpress,UniDAC,AnyDac,...    
  AdoQuery1.Active:=true;
end;

use generate proxy for client side

// Client Code
procedure TForm1.Button1Click(Sender:TObject);
begin
  Proxy.ChangeSQL('select * from custom_table');// but it is insecure
  // loading remote datasets
end;


来源:https://stackoverflow.com/questions/10535301/execute-dynamic-sql-in-datasnap-client

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!