DataSnap 多层返回数据集分析FireDAC JSON
2015-02-09 11:50
477 查看
采用服务器返回数据,一种是返回字符串数据例如JSON,跨平台跨语言,任何语言调用都支持兼容,类似WEBService。
第二种是紧密结合c++builder语言,传输DataSet,可以是ClientDataSet,也可以是FDMemTable,或TDataSet,这类好处是DataSet本身包含了很多属性,记录集的状态Insert/Modify/Delete,在服务端可以调用
不同的方法进行数据处理,客户端也只需要把dataset对象赋值就展示到dbgrid里了。
序列化。
Serever
String GetPersonAll()
{
return "";字符串形式的JSON或XML格式
}
Client
String DataSTR=srv->GetPersonAll();
对字符串解析JSON或XML,以DataSet展示就可以。
用第三方库SuperJson也可以。
http://blog.csdn.net/ddqqyy/article/details/6174525 讲的是返回dataset ClientDataSet1.Delta,TDataSetProvider,TSqlServerMethod,还用到了OleVariant
#include <Data.DBXCDSReaders.hpp>
static void __fastcall CopyReaderToClientDataSet(Data::Dbxcommon::TDBXReader* Reader, Datasnap::Dbclient::TClientDataSet* Dataset);
static Datasnap::Dbclient::TClientDataSet* __fastcall ToClientDataSet(TComponent* AOwner, Data::Dbxcommon::TDBXReader* Reader, bool AOwnsInstance);
C++中这些返回指针,怎么释放一直没想清楚。
{
ClientDataSet1->Open();
adata = this->ClientDataSet1->Data;
return this->ClientDataSet1->RecordCount;
}
DataSetProvider1也有Data属性。
OleVariant Data
DataSetProvider1->Data;
只能用ClientDataSet1,其他的数据集都没有data属性,有data属性的FDQuery类型也不是OleVariant 。
ClientDataSet:OleVariant Data
FDQuery:_di_IFDDataSetReference Data
#include "Data.DBXCDSReaders.hpp"
Client
reader= CallProxy.GetDSReader();
TDBXClientDataSetReader::CopyReaderToClientDataSet(reader,cds);
cds->Open();
fdquery
DataSetProvider1.DataSet=fdquery;
DataSetProvider1.Option.poAllowCommandText=true;
客户端
SQLConnection1
TDSProviderConnection.sqlconnection=SQLConnection1
TDSProviderConnection.serverclassname =tServerMethods1
ClientDataSet.RemoteServer=DSProviderConnection1
ClientDataSet.providername =DataSetProvider1
ClientDataSet.open();
ok!
Client
or serverProxy eg
FUnMarshal := TDSRestCommand(FGetDepartmentNamesCommand.Parameters[0].ConnectionHandler).GetJSONUnMarshaler;
Result := TFDJSONDataSets(FUnMarshal.UnMarshal(FGetDepartmentNamesCommand.Parameters[0].Value.GetJSONValue(True)));
View Code
第二种是紧密结合c++builder语言,传输DataSet,可以是ClientDataSet,也可以是FDMemTable,或TDataSet,这类好处是DataSet本身包含了很多属性,记录集的状态Insert/Modify/Delete,在服务端可以调用
不同的方法进行数据处理,客户端也只需要把dataset对象赋值就展示到dbgrid里了。
序列化。
一、跨平台纯字符串
对返回的数据增删改查。对应的方法就是Add/Delete/Update/Query,客户端调用此方法就OK了。Serever
String GetPersonAll()
{
return "";字符串形式的JSON或XML格式
}
Client
String DataSTR=srv->GetPersonAll();
对字符串解析JSON或XML,以DataSet展示就可以。
function TServerMethods1.GetData(SQL: String): String; var aCommand: TDBXCommand; aReader: TDBXReader; begin Result := ''; aCommand := SQLConnection1.DBXConnection.CreateCommand; // 指定 SQLConnection1 连接数据库 try aCommand.Text := SQL; // 指定SQL语句 aReader := aCommand.ExecuteQuery; Result := TDBXJSONTools.TableToJSON(aReader, 10, True).ToString; finally aCommand.Free; end; end;
用第三方库SuperJson也可以。
二、DataSet
http://blog.csdn.net/ddqqyy/article/details/6982164 利用TDBXDataSetReader实例化,传输的是TDBXReaderhttp://blog.csdn.net/ddqqyy/article/details/6174525 讲的是返回dataset ClientDataSet1.Delta,TDataSetProvider,TSqlServerMethod,还用到了OleVariant
#include <Data.DBXCDSReaders.hpp>
static void __fastcall CopyReaderToClientDataSet(Data::Dbxcommon::TDBXReader* Reader, Datasnap::Dbclient::TClientDataSet* Dataset);
static Datasnap::Dbclient::TClientDataSet* __fastcall ToClientDataSet(TComponent* AOwner, Data::Dbxcommon::TDBXReader* Reader, bool AOwnsInstance);
C++中这些返回指针,怎么释放一直没想清楚。
三、返回ClientDataSet1的OleVariant
int TServerMethods1::GetTableDataSet(String atableName, OleVariant adata){
ClientDataSet1->Open();
adata = this->ClientDataSet1->Data;
return this->ClientDataSet1->RecordCount;
}
DataSetProvider1也有Data属性。
OleVariant Data
DataSetProvider1->Data;
只能用ClientDataSet1,其他的数据集都没有data属性,有data属性的FDQuery类型也不是OleVariant 。
ClientDataSet:OleVariant Data
FDQuery:_di_IFDDataSetReference Data
四、返回TDBXReader
TDBXReader 可以自己释放内存,所以不必担心内心释放泄露的问题了。#include "Data.DBXCDSReaders.hpp"
TDBXReader* TServerMethods1::GetDSReader(String asql) { TDBXCommand *cmd; TDBXReader *reader; TClientDataSet *cds; cmd = SQLConnection1.DBXConnection.CreateCommand; cmd->Text = asql; reader = cmd->ExecuteQuery(); return reader; //or cds = TDBXClientDataSetReader::ToClientDataSet(NULL, reader, true); return new TDBXClientDataSetReader(cds, true); }
Client
reader= CallProxy.GetDSReader();
TDBXClientDataSetReader::CopyReaderToClientDataSet(reader,cds);
cds->Open();
五、用ClientDataSet
服务端:fdquery
DataSetProvider1.DataSet=fdquery;
DataSetProvider1.Option.poAllowCommandText=true;
客户端
SQLConnection1
TDSProviderConnection.sqlconnection=SQLConnection1
TDSProviderConnection.serverclassname =tServerMethods1
ClientDataSet.RemoteServer=DSProviderConnection1
ClientDataSet.providername =DataSetProvider1
ClientDataSet.open();
ok!
六、返回TFDJSONDataSets
TFDJSONDataSets可以返回多个数据集。这个是以后的趋势!REST Client server
function TServerMethods1.GetJSONData: TFDJSONDataSets; begin Result := TFDJSONDataSets.Create; if not FDMemTable1.Active then FDMemTable1.LoadFromFile('../../customer.fds') else FDMemTable1.Active := False; TFDJSONDataSetsWriter.ListAdd(Result, FDMemTable1); end;
Client
var DSList: TFDJSONDataSets; begin FDMemTable1.Close; DSList := ClientModule1.ServerMethods1Client.GetJSONData; FDMemTable1.AppendData( TFDJSONDataSetsReader.GetListValue(DSList, 0)); FDMemTable1.Open; end;
or serverProxy eg
FUnMarshal := TDSRestCommand(FGetDepartmentNamesCommand.Parameters[0].ConnectionHandler).GetJSONUnMarshaler;
Result := TFDJSONDataSets(FUnMarshal.UnMarshal(FGetDepartmentNamesCommand.Parameters[0].Value.GetJSONValue(True)));
七、返回TJSONArray
未实行八、FireDAC
FireDAC
TFDJSONDataSets C++Builder http://blogs.embarcadero.com/pawelglowacki/2014/06/04/40330/ Delphi http://blogs.embarcadero.com/fernandorizzato/index.php/2014/07/21/multi-tier-com-delphi-xe6-e-firedac-json-reflection/ http://www.cnblogs.com/hnxxcxg/p/4007876.html http://www.cnblogs.com/hnxxcxg/p/4008789.html http://www.kzx123.com/?p=105 http://blog.marcocantu.com/blog/delphi_xe5_update2_datasnap_firedac.html D:\Users\Public\Documents\Embarcadero\Studio\15.0\Samples\Object Pascal\DataSnap\FireDACJSONReflect TFDJSONDataSets *dset; TFDJSONDataSetsReader * dsread; TFDJSONDataSetsWriter::ListAdd(dset, FDMemTable1);//FDQuery1 TFDJSONDataSets 是DataSet的集合,数据集的集合,可以持有多个DataSet。 FDQuery1,FDMemTable1其实也可以有多个数据集,也算是数据集的集合,取下一个数据集FDQuery1.NextRecordSet 下面sql返回2个数据集。 FDQuery1.SQL.Text := 'select * from orders; select * from customers'; Data.FireDACJSONReflect.hpp 返回值可以是 TFDJSONDataSets,TJSONObject*,TFDJSONDeltas 通过 TFDJSONInterceptor::DataSetsToJSONObject()把TFDJSONDataSets转为TFDJSONDataSets。
Skip to content This repository Explore Features Enterprise Pricing 1 0 0 flrizzato/FireDACJSONReflectionXE7 FireDACJSONReflectionXE7/ServerMethodsUnit1.pas Git User on 15 Oct 2014 first version 0 contributors 219 lines (188 sloc) 6.751 kB // // FireDACJSONReflect demo // Copyright (c) 1995-2013 Embarcadero Technologies, Inc. // You may only use this software if you are an authorized licensee // of Delphi, C++Builder or RAD Studio (Embarcadero Products). // This software is considered a Redistributable as defined under // the software license agreement that comes with the Embarcadero Products // and is subject to that software license agreement. // unit ServerMethodsUnit1; interface uses System.SysUtils, System.Classes, Datasnap.DSServer, Datasnap.DSAuth, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf, FireDAC.DApt.Intf, FireDAC.Stan.Async, FireDAC.DApt, FireDAC.UI.Intf, FireDAC.VCLUI.Wait, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Phys, Data.DB, FireDAC.Comp.Client, FireDAC.Phys.IBBase, FireDAC.Phys.IB, FireDAC.Comp.UI, FireDAC.Comp.DataSet, Data.FireDACJSONReflect, System.JSON, FireDAC.Stan.StorageBin, FireDAC.Stan.StorageJSON, FireDAC.Phys.IBDef; type {$METHODINFO ON} TServerMethods1 = class(TDataModule) FDQueryDepartmentEmployees: TFDQuery; FDQueryDepartment: TFDQuery; FDQueryDepartmentNames: TFDQuery; FDGUIxWaitCursor1: TFDGUIxWaitCursor; FDPhysIBDriverLink1: TFDPhysIBDriverLink; FDConnectionEMPLOYEE: TFDConnection; FDStanStorageJSONLink1: TFDStanStorageJSONLink; FDQueryDepartmentDEPT_NO: TStringField; FDQueryDepartmentDEPARTMENT: TStringField; FDQueryDepartmentHEAD_DEPT: TStringField; FDQueryDepartmentMNGR_NO: TSmallintField; FDQueryDepartmentBUDGET: TBCDField; FDQueryDepartmentLOCATION: TStringField; FDQueryDepartmentPHONE_NO: TStringField; procedure DataModuleCreate(Sender: TObject); public { Public declarations } function EchoString(Value: string): string; function ReverseString(Value: string): string; // Strongly typed methods function GetDepartmentNames: TFDJSONDataSets; function GetDepartmentEmployees(const AID: string): TFDJSONDataSets; procedure ApplyChangesDepartmentEmployees(const ADeltaList: TFDJSONDeltas); // Equivalent TJSONObject methods (C++ compatible) function GetDepartmentNamesJSON: TJSONObject; function GetDepartmentEmployeesJSON(const AID: string): TJSONObject; procedure ApplyChangesDepartmentEmployeesJSON(const AJSONObject : TJSONObject); function FileDownload(sFileName: string): TStream; procedure FileUpload(fStream: TStream); end; {$METHODINFO OFF} implementation {$R *.dfm} uses System.StrUtils, System.Generics.Collections; const sDepartment = 'Department'; sEmployees = 'Employees'; sDataDir = 'c:\temp\'; // Get a Department and all Employees in the department. Result TFDJSONDataSets. function TServerMethods1.GetDepartmentEmployees(const AID: string) : TFDJSONDataSets; begin // Clear active so that query will reexecute FDQueryDepartmentEmployees.Active := False; FDQueryDepartment.Active := False; FDQueryDepartment.Params[0].Value := AID; FDQueryDepartmentEmployees.Params[0].Value := AID; // Create dataset list Result := TFDJSONDataSets.Create; // Add departments dataset TFDJSONDataSetsWriter.ListAdd(Result, sDepartment, FDQueryDepartment); // Add employees dataset TFDJSONDataSetsWriter.ListAdd(Result, sEmployees, FDQueryDepartmentEmployees); end; // Get a Department and all Employees in the department. Return TJSONObject. function TServerMethods1.GetDepartmentEmployeesJSON(const AID: string) : TJSONObject; var LDataSets: TFDJSONDataSets; begin LDataSets := GetDepartmentEmployees(AID); try Result := TJSONObject.Create; TFDJSONInterceptor.DataSetsToJSONObject(LDataSets, Result) finally LDataSets.Free; end; end; // Update department and employees using deltas. TFDJSONDeltas parameter. procedure TServerMethods1.ApplyChangesDepartmentEmployees(const ADeltaList : TFDJSONDeltas); var LApply: IFDJSONDeltasApplyUpdates; begin // Create the apply object LApply := TFDJSONDeltasApplyUpdates.Create(ADeltaList); // Apply the department delta LApply.ApplyUpdates(sDepartment, FDQueryDepartment.Command); if LApply.Errors.Count = 0 then // If no errors, apply the employee delta LApply.ApplyUpdates(sEmployees, FDQueryDepartmentEmployees.Command); if LApply.Errors.Count > 0 then // Raise an exception if any errors. raise Exception.Create(LApply.Errors.Strings.Text); end; // Update department and employees using deltas. TJSONObject parameter. procedure TServerMethods1.ApplyChangesDepartmentEmployeesJSON(const AJSONObject : TJSONObject); var LDeltas: TFDJSONDeltas; begin LDeltas := TFDJSONDeltas.Create; TFDJSONInterceptor.JSONObjectToDataSets(AJSONObject, LDeltas); ApplyChangesDepartmentEmployees(LDeltas); end; procedure TServerMethods1.DataModuleCreate(Sender: TObject); begin end; // Get all Departments. Result TFDJSONDataSets. function TServerMethods1.GetDepartmentNames: TFDJSONDataSets; begin // Clear active so that query will reexecute FDQueryDepartmentNames.Active := False; Result := TFDJSONDataSets.Create; TFDJSONDataSetsWriter.ListAdd(Result, FDQueryDepartmentNames); end; // Get all Departments. Result TFDJSONDataSets; function TServerMethods1.GetDepartmentNamesJSON: TJSONObject; var LDataSets: TFDJSONDataSets; begin LDataSets := GetDepartmentNames; try Result := TJSONObject.Create; TFDJSONInterceptor.DataSetsToJSONObject(LDataSets, Result); finally LDataSets.Free; end; end; function TServerMethods1.EchoString(Value: string): string; begin Result := Value; end; function TServerMethods1.FileDownload(sFileName: string): TStream; var fFileStream: TFileStream; begin fFileStream := TFileStream.Create(sDataDir + sFileName, fmOpenRead); Result := fFileStream; end; procedure TServerMethods1.FileUpload(fStream: TStream); var fMemStream: TMemoryStream; BytesRead: integer; sFileName: string; Buffer: PByte; const MaxBufSize = 1024 * 1024; begin sFileName := sDatadir + 'file-to-upload-copy.jpg'; DeleteFile(sFileName); if not FileExists(sFileName) then begin fMemStream := TMemoryStream.Create; try fStream.Seek(0, TSeekOrigin.soBeginning); fStream.Position := 0; GetMem(Buffer, MaxBufSize); repeat BytesRead := fStream.Read(Buffer^, MaxBufSize); if BytesRead > 0 then fMemStream.WriteBuffer(Buffer^, BytesRead); until BytesRead < MaxBufSize; fMemStream.Seek(0, TSeekOrigin.soBeginning); fMemStream.SaveToFile(sFileName); finally fMemStream.Free; end; end; end; function TServerMethods1.ReverseString(Value: string): string; begin Result := System.StrUtils.ReverseString(Value); end; end. Status API Training Shop Blog About Pricing © 2015 GitHub, Inc. Terms Privacy Security Contact Help
View Code
相关文章推荐
- DataSnap 多层返回数据集分析FireDAC JSON
- 多层数据库应用基于Delphi DataSnap方法调用的实现(一)返回数据集
- 多层数据库应用基于Delphi DataSnap方法调用的实现(一)返回数据集
- 调用DATASNAP+FIREDAC的远程方法有时会执行二次SQL或存储过程的BUG
- FireDAC DataSnap
- DataSnap Server HTTP json格式修改 返回图片
- 多层数据库应用基于Delphi DataSnap方法调用的实现(四)BLOB字段的读写
- 多层数据库应用基于Delphi DataSnap方法调用的实现-----------------对象池技术
- DataSnap与JSON序列化(4)
- ADO.NET Data Service如何直接支持用Json格式返回数据
- jQuery备忘之(一):jQuery处理.Net后台返回的Xml格式与Json格式的数据的比较分析
- 多层数据库应用基于Delphi DataSnap方法调用的实现(四)BLOB字段的读写
- ADO.NET Data Service如何直接支持用Json格式返回数据
- 中国天气网接口返回json格式分析及接口(XML、图片接口)说明!
- 中国天气网接口 返回json格式分析说明
- DataSnap服务器方法返回TClientDataSet的简易实现
- sqldatareader返回数据集,并要求使用ADO.net事务的解决方案
- Tiburon遊記2 DataSnap和JSON
- Delphi 的一个加密和压缩组件 (用于DataSnap多层程序中)