A5 Delphi/C++

DataSnap 2010• DataSnap 2010(2009)?

••Demo•• ZLibCompression•<---->+• C++Builder 2010•••

DemoAdvanced!

••

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

2

DataSnap 2010(2009)?

DataSnap

GUI,SQLBDE etc…

GUIetc…

RDBMS

SQL

GUI

DataSnap

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

DataSnap

dbExpress等

DataSnap

TCP/IP
orHTTP

etc…

RDBMS

4

DataSnap• TCP/IP•211• SSL, IPv6

• HTTP•80• SSL IISISAPI/CGI• RPC{"method":"connect","params":"drivername":"DATASNAP","port":"211","communicationprotocol":"tcp/ip","hostname":"127.0.0.1","DriverUnit":"DbxDatasnap",....]}{"method":"execute","params":[{"fields":[1,false,"Dbx.MetaData","GetDatabase"]}]}{"method":"reader_close","params":[1,0]}{"method":"disconnect","params":[0]}•••RDBMS!!

– in, var, out, inout, return••• Server, Session, Invocation• Callback, Filter, Event•• JSON(JavaScript Object Notation)
Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

{"result":[0,"DataSnap",2]}{"result":[{"rows":[0]},{"data":[1,`]},{"table":[{"fields":[0,false,1,0,true]},{"columns":[13,["QuoteChar",26,0,0,0,16,0,0],["ProcedureQuoteChar",26,0,0,0,16,0,0],["MaxCommands",6,0,0,0,0,0,0],["SupportsTransacti
ons",4,0,0,0,0,0,0],["SupportsNestedTransactions",4,0,0,0,0,0,0],["SupportsRowSetSize",4,0,0,0,0,0,0]...
...
...

5

DataSnap• TDSServer•

DataSnap• TDSServerClass•• TDSTCPServerTransport•

TCP/IP• TDSHTTPService•

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

HTTP6••••••••••••••••••••

AnsiString
Boolean
Byte
Currency
TDateTimeTDBXDate
TDBXTime
DoubleInt64
Integer
LongInt
OleVariantSingle
ShortInt
SmallInt
String(UnicodeString)
WideString
TStream

DBXValue
•••
•
•
••••
•••
•
••
•
•
•••

TDBXAnsiStringValueTDBXAnsiCharsValueTDBXBcdValueTDBXBooleanValueTDBXDateValueTDBXDoubleValueTDBXUInt8ValueTDBXInt8ValueTDBXInt16ValueTDBXInt32ValueTDBXInt64ValueTDBXJSonValueTDBXReaderValueTDBXSingleValueTDBXStringValueTDBXTimeStampValueTDBXTimeValueTDBXWideCharsValueTDBXWideStringValueTDBXStreamValue

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

•••••

TDataSet
TParams
TDBXReader

JSON (REST•••••

DBXValue)

TJSONArrayTJSONNumber
TJSONObject
TJSONString
TJSONValue

NULLvarOK

inoutvar

NULLNG

inoutvar

OK7?

• DataSnap(TBytes)•(• TDSTCPServerTransport• TDSHTTPService• Filters)
FiltersFilters

FilterId•••

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

(: ‘ZLibCompression’)dbExpress

dbExpress

Filter A

Filter A

Filter B

Filter B

TCP/IP, HTTP

TCP/IP, HTTP
9• DBXTransport

TTransportFilter• 7• ProcessInput

ProcessOutput– TBytes(=array of Byte)•

TBytes(.pas)(.bpl)IDE• IDE

dbExpress

デコード

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

エンコード

デコード

エンコード

TCP/IP, HTTP

dbExpress

TCP/IP, HTTP

10

DSFEncryptClasses.pas
type
TTransportEncryptFilter = class(TTransportFilter
TTransportFilter)
TTransportFilter
privateFParameters: TDictionary<String, String>;
protected
function GetParameters: TDBXStringArray; override;function GetUserParameters: TDBXStringArray; override;
publicconstructor Create; override;
destructor Destroy; override;function GetParameterValue(const ParamName: UnicodeString): UnicodeString; override;function SetParameterValue(const ParamName: UnicodeString; const ParamValue: UnicodeString): Boolean; override;function ProcessInput(const Data: TBytes): TBytes; override;function ProcessOutput(const Data: TBytes): TBytes; override;function Id: UnicodeString; override;end;
const
EncryptFilterName = 'EncryptionFilter';'EncryptionFilter'
EncryptKey = 'Key';initialization
TTransportFilterFactory.RegisterFilter(EncryptFilterName, TTransportEncryptFilter);TTransportEncryptFilter);
finalization
TTransportFilterFactory.UnregisterFilter(EncryptFilterName);
end.

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

11

DSFEncryptClasses.pas
constructor TTransportEncryptFilter.Create;
begininherited;
FParameters := TDictionary<String, String>.Create;
end;
destructor TTransportEncryptFilter.Destroy;
begin
FreeAndNil(FParameters);
inherited;end;
function TTransportEncryptFilter.Id: UnicodeString;
begin
Result := EncryptFilterName;
EncryptFilterName
end;function TTransportEncryptFilter.SetParameterValue(const ParamName, ParamValue: UnicodeString): Boolean;
begin
FParameters.AddOrSetValue(ParamName, ParamValue);
Result := True;
end;
function TTransportEncryptFilter.GetParameterValue(const ParamName: UnicodeString): UnicodeString;
begin
FParameters.TryGetValue(ParamName, Result);
if (ParamName = EncryptKey) and (Result = '') then
Result := '0'; //end;

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

function TTransportEncryptFilter.GetUserParameters: TDBXStringArray;
beginSetLength(Result, 1);
Result[0] := EncryptKey;
end;function TTransportEncryptFilter.GetParameters: TDBXStringArray;
begin
SetLength(Result, 1);
Result[0] := EncryptKey;
end;function TTransportEncryptFilter.ProcessInput
ProcessInput(const
Data: TBytes):
ProcessInput
TBytes TBytes;
TBytesvar
param: UnicodeStrting
begin
param := GetParameterValue(EncryptKey);
Result := ...; //end;function TTransportEncryptFilter.ProcessOutput
ProcessOutput(const
Data: TBytes):
ProcessOutput
TBytesTBytes;
TBytesvar
param: UnicodeStrting
begin
param := GetParameterValue(EncryptKey);
Result := ...; //
end;

12••

OK• uses•()uses…, DSFEncryptClasses,
DSFEncryptClasses DbxCompressionFilter, …
…
procedure TServerForm.FormCreate(Sender: TObject);var
i: Integer;
begin//
i := DSTCPServerTransport1.Filters.AddFilter('EncryptionFilter');
DSTCPServerTransport1.Filters.AddFilter
DSTCPServerTransport1.Filters.GetFilter(i).SetParameterValue('Key', '100');//
for i := 0 to DSTCPServerTransport1.Filters.Count - 1 do
ListBox1.Items.Add(DSTCPServerTransport1.Filters.GetFilter(i).Id);
end;

()

uses
…, DSFEncryptClasses,
DSFEncryptClasses DbxCompressionFilter, …

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

13

C++Builder 2010

C++

DataSnap•C++• C++Builder••.pas.pas&.pas• C++•• TDSServerClass•
Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

C++
OnCreateInstance

OnDestroyInstance

VCL

15

C++

DataSnap
ServerMethodsUnit1.pas

unit ServerMethodsUnit1;
interface
uses
SysUtils, Classes, DSServer;
type
TAbstractServerMethods = classpublicfunction EchoString(Value: string): string; virtual; abstract;
end;{$METHODINFO ON}
TServerMethods1 = class(TPersistent)
public
impl: TAbstractServerMethods;
function EchoString(Value: string): string;end;{$METHODINFO OFF}C++(.hpp)

ServerMethodsUnit1.hpp

namespace Servermethodsunit1 {class PASCALIMPLEMENTATION TAbstractServerMethods : public System::TObject {public:virtual System::UnicodeString __fastcall EchoString(System::UnicodeString Value) = 0 ;public:implementation__fastcall TAbstractServerMethods(void) : System::TObject() { }function TServerMethods1.EchoString(Value: string): string;__fastcall virtual ~TAbstractServerMethods(void) { }begin};
Result := impl.EchoString(Value);end;class PASCALIMPLEMENTATION TServerMethods1 : public Classes::TPersistent {public:end.
TAbstractServerMethods* impl;
System::UnicodeString __fastcall EchoString(System::UnicodeString Value);
public:__fastcall TServerMethods1(void) : Classes::TPersistent() { }__fastcall virtual ~TServerMethods1(void) { }};}Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

16

C++

DataSnap()#include "ServerMethodsUnit1.hpp
ServerMethodsUnit1.hpp"
ServerMethodsUnit1.hpp
class TServerMethodsImpl : public TAbstractServerMethods {public:__fastcall TServerMethodsImpl() : TAbstractServerMethods() { }__fastcall virtual ~TServerMethodsImpl() { }public:System::UnicodeString __fastcall EchoString(System::UnicodeString Value) {return Value;}};

TDSServerClass

OnCreateInstance

OnDestroyInstance

void __fastcall TForm1::DSServerClass1GetClass(TDSServerClass *DSServerClass,TPersistentClass &PersistentClass){PersistentClass = __classid(TServerMethods1);}
void __fastcall TForm1::DSServerClass1CreateInstance(TDSCreateInstanceEventObject *DSCreateInstanceEventObject){TServerMethods1* inst = new TServerMethods1();
instinst->impl = new TServerMethodsImpl();
DSCreateInstanceEventObjectDSCreateInstanceEventObject->ServerClassInstance = inst;}
void __fastcall TForm1::DSServerClass1DestroyInstance(TDSDestroyInstanceEventObject *DSDestroyInstanceEventObject){*)DSDestroyInstanceEventObject
entObjectTServerMethods1* inst = (TServerMethods1 *)DSDestroyInstanceEv
entObject->ServerClassInstance;
delete instinst->impl;
delete inst;}
Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

17

C++DataSnap• Delphi

TSQLConnection DataSnap•• Delphi•

TSQLServerMethod(.h, .cpp)#include "Unit2.h"#ifndef Unit2H...
#define Unit2H
static TServerMethods1Client* proxy = NULL;#include "DBXCommon.hpp"
void __fastcall TForm1::Button1Click(TObject *Sender)#include "Classes.hpp"{#include "SysUtils.hpp"
if (proxy == NULL) {proxy = new TServerMethods1Client(localcpp
localcpp#include "DB.hpp"
localcpp->DBXConnection);>DBXConnection}#include "SqlExpr.hpp"
UnicodeString test = L"";
#include "DBXDBReaders.hpp"
UnicodeString ret = proxy->EchoString(test);class TServerMethods1Client : public TObject {ShowMessage(ret);private:}TDBXConnection *FDBXConnection;bool FInstanceOwner;
TDBXCommand *FEchoStringCommand;
public:__fastcall TServerMethods1Client::TServerMethods1Client(TDBXConnection *ADB*ADBXConnection);
XConnection);__fastcall TServerMethods1Client::TServerMethods1Client(TDBXConnection *ADBXConnection, bool AInstanceOwner);__fastcall TServerMethods1Client::~TServerMethods1Client();
System::UnicodeString __fastcall EchoString(System::UnicodeString Value);};
Copyright#endif ©2009 Embarcadero Technologies, Inc. All Rights Reserved.
18

Tips: C++•……
delete•__fastcall TServerMethods1Client::~TServerMethods1Client(){
FreeAndNil(FEchoStringCommand);}__fastcall TServerMethods1Client::~TServerMethods1Client(){
delete FEchoStringCommand;
FEchoStringCommand = NULL;}

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

19• Server•• Session•• Invocation•&DataSnapCopyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

RDBMS21

unit MyDBXPool;uses
SysUtils, Classes, SqlExpr, Generics.Collections;
type
TMyDBXPool = class(TComponent)
privateFRootConnection: TSQLConnection;
FMaxPoolSize: Integer;
FLock: TObject;
FPool: TList<TSQLConnection>;
TList<TSQLConnection>
FBusy: TList<TSQLConnection>;
TList<TSQLConnection>
procedure SetRootConnection(const Value: TSQLConnection);
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
publicconstructor Create(AOwner: TComponent); override;
destructor Destroy; override;function GetPooledConnection: TSQLConnection;
procedure ReturnPooledConnection(conn: TSQLConnection);function GetPooledCount: Integer;
publishedproperty RootConnection: TSQLConnection read FRootConnection write
write SetRootConnection;
property MaxPoolSize: Integer read FMaxPoolSize write FMaxPoolSize default 0;
end;…
…
initialization
IsMultiThread := True;
end.

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

22

constructor TMyDBXPool.Create(AOwner: TComponent);
begin
inherited;
RootConnection := nil;
FMaxPoolSize := 0;
FLock := TObject.Create;
FPool := TList<TSQLConnection>.Create;
FBusy := TList<TSQLConnection>.Create;
end;
destructor TMyDBXPool.Destroy;
begin
FreeAndNil(FBusy);
while FPool.Count > 0 do
begin
try
FPool.Items[0].Connected := False;
except on E: Exception do
end;
FPool.Items[0].Free;
FPool.Delete(0);end;
FreeAndNil(FPool);
FreeAndNil(FLock);inherited;end;

procedure TMyDBXPool.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited;
if (Operation = opRemove) and (AComponent = FRootConnection) thenFRootConnection := nil;end;
procedure TMyDBXPool.SetRootConnection(const Value: TSQLConnection);
begin
if FRootConnection <> Value thenbegin
if Assigned(FRootConnection) thenFRootConnection.RemoveFreeNotification(Self);
if Assigned(Value) thenValue.FreeNotification(Self);
FRootConnection := Value;
end;
end;

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

23

(function TMyDBXPool.GetPooledConnection: TSQLConnection;
begin
Result := nil;
if not Assigned(FRootConnection) thenExit;System.TMonitor.Enter(FLock);try
while True do
begin
if FPool.Count <= 0 thenbegin
if (FMaxPoolSize <= 0) or (FBusy.Count < FMaxPoolSize) thenBreak;
while FPool.Count <= 0 do
begin
try
System.TMonitor.Wait(FLock, 100);
except on E: Exception do
end;
end;
end;
Result := FPool.Items[0];FPool.Delete(0);FBusy.Add(Result);
Exit;end;
Result := TSQLConnection.Create(nil);
Result.ConnectionName := 'CONN' + IntToStr(Integer(Pointer(Result)));Result.DriverName:= FRootConnection.DriverName;
Result.GetDriverFunc := FRootConnection.GetDriverFunc;
Result.LibraryName:= FRootConnection.LibraryName;
Result.LoginPrompt:= False;
Result.KeepConnection := True;
Result.Params.Assign(FRootConnection.Params);
try
Result.Connected := True;
FBusy.Add(Result);
except on E: Exception do
FreeAndNil(Result);
end;
finally
System.TMonitor.Exit(FLock);end;
Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.
end;)

procedure TMyDBXPool.ReturnPooledConnection(conn: TSQLConnection);vari: Integer;
begin
System.TMonitor.Enter(FLock);tryi := FBusy.IndexOf(conn);
if i >= 0 then
FBusy.Delete(i);if Assigned(conn) thenFPool.Add(conn);
System.TMonitor.PulseAll(FLock);
finally
System.TMonitor.Exit(FLock);
end;
end;
function TMyDBXPool.GetPooledCount: Integer;
begin
System.TMonitor.Enter(FLock);try
Exit(FPool.Count);
finally
System.TMonitor.Exit(FLock);
end;
end;

24

Q&A

Q&A

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.

25