这个问题与我以前的问题直接相关。
我需要从包装中包含的Oracle 11G光标上在客户端上创建一个TCLIENTDATASET。我正在使用Delphi XE2和DBExpress连接到DB和DatasNap以将数据发送回客户端。
当我在设计时间将TSQLStoredProc配置为TCLIENTDATASET时,我可以将光标返回作为TCLIENTDATASET,毫无问题并获得预期结果。
当我尝试在运行时执行存储过程时,它会返回一个空的tclientdataset。
是否可以在运行时使用TSQLStoredProc配置和执行Oracle 11G存储过程?
DataSnap服务器
设计时间数据模块代码[查看为文本]
object StrProc1: TSQLStoredProc
SchemaName = 'xxxx'
MaxBlobSize = -1
Params = <
item
DataType = ftWideString
Precision = 2000
Name = 'ABBR'
ParamType = ptInput
Value = 'ZZZTOP'
end
item
DataType = ftCursor
Precision = 8000
Name = 'RES'
ParamType = ptOutput
Size = 8000
end>
PackageName = 'KP_DATASNAPTEST'
SQLConnection = SQLConnection1
StoredProcName = 'GETFAXDATA'
Left = 408
Top = 72
end
object DataSetProvider1: TDataSetProvider
DataSet = StrProc1
Left = 408
Top = 120
end
object ClientDataSet1: TClientDataSet
Aggregates = <>
Params = <>
ProviderName = 'DataSetProvider1'
Left = 408
Top = 176
end
函数执行设计时间config
function TKPSnapMethods.getCDS_Data3: OLEVariant;
begin
self.ClientDataSet1.Open;
result:= self.ClientDataSet1.Data;
self.SQLConnection1.Close;
end;
函数要执行运行时配置这是返回空clientdataset的代码。目的是连接零件,设置参数的值,打开CD并返回cds.data
function TKPSnapMethods.getCDS_Data2(schema: String): OleVariant;
var
cds: TClientDataSet;
dsp: TDataSetProvider;
strProc: TSQLStoredProc;
ProcParams: TList;
begin
strProc := TSQLStoredProc.Create(self);
try
strProc.SQLConnection:= SQLCon;//<--A TSQLConnection
dsp := TDataSetProvider.Create(self);
try
dsp.DataSet := strProc;
cds := TClientDataSet.Create(self);
try
cds.DisableStringTrim := True;
cds.ReadOnly := True;
cds.SetProvider(dsp);
ProcParams:= TList.Create;
try
//Load Stored Procedure Parameters
SQLCon.GetProcedureParams('GETFAXDATA','KP_DATASNAPTEST',Schema,ProcParams);
LoadParamListItems(StrProc.Params,ProcParams);
strProc.ParamByName('ABBR').AsString := 'ZZZTOP';//<--Assign Parms
strProc.MaxBlobSize := -1;
strProc.SchemaName:= Schema;
strproc.PackageName:='KP_DATASNAPTEST';
strProc.StoredProcName:= 'GETFAXDATA';
cds.Open;
Result := cds.Data;
finally
FreeProcParams(ProcParams);
end;
finally
FreeAndNil(cds);
end;
finally
FreeAndNil(dsp);
end;
finally
FreeAndNil(strProc);
self.SQLCon.Close;
end;
end;
客户端代码这只是一个测试表格,它可以创建与DataSnap服务器的连接执行ServerMethods并在字符串网格中显示结果。
procedure TForm1.Button1Click(Sender: TObject);
var
proxy:TKpSnapMethodsClient;
cds :TClientDataSet;
field: TField;
r,c:integer;
begin
r:=0;
c:=0;
SQLConTCPSERV.Connected := True; //TSQLConnection
proxy:= TKPSnapMethodsClient.Create(SQLConTCPSERV.DBXConnection,false);
cds:= TClientDataSet.Create(nil);
try
//cds.Data:= proxy.getCDS_Data2('TESTTH');//<--Runtime function
cds.Data:= proxy.getCDS_Data3; //<--Design time function
if cds <> nil then
begin
cds.Open;
cds.First;
//String grid to display CDS contents.
strGrid1.ColCount:= cds.FieldCount; //returns correct #
strGrid1.RowCount:= cds.RecordCount;
while not cds.Eof do //<--runtime wont make it past here
begin
for field in cds.fields do //loop fields
begin
strgrid1.Cells[c,r]:= field.Text; //display results.
c:=c+1;
end;
c:=0;
r:=r+1;
cds.Next;
end;
end
else showmessage('DataSet is NIL');
finally
cds.Free;
proxy.Free;
SQLConTCPSERV.Connected := False;
end;
end;
Agian一旦我承认我是Delphi语言的新手。我已经搜索了Google,Code.google,Embarcadero开发人员网络和DBExpress文档,无济于事。我只是不明白为什么设计时间和运行时会有区别。
我已经解决了问题。问题在于将值分配给TSQLStordProc组件的顺序。
调用此代码时:
strproc.PackageName:='KP_DATASNAPTEST';
strProc.StoredProcName:= 'GETFAXDATA';
清除参数。以下是设置data.sqlexpr
中的storedProcname的代码。procedure TSQLStoredProc.SetStoredProcName(Value: UnicodeString);
begin
//if FStoredProcName <> Value then
//begin
FStoredProcName := Value;
SetCommandText(Value);
if Assigned(FProcParams) then // free output params if any
FreeProcParams(FProcParams);
//end;
end;
您可以查看是否分配了fprocparams,则呼叫freeprocparams可以释放参数。因为我在分配了参数值之后设置了stroredProcname,代码正在用清除的params执行并返回一个空光标。
在运行时产生正确结果的顺序[从getCDS_DATA2]如下:
strProc.SchemaName:= Schema;
SQLCon.GetProcedureParams('GETFAXDATA','KP_DATASNAPTEST',Schema,ProcParams);
LoadParamListItems(StrProc.Params,ProcParams);
strproc.PackageName:='KP_DATASNAPTEST';
strProc.StoredProcName:= 'GETFAXDATA';
strProc.MaxBlobSize := -1;
strProc.ParamCheck:=true;
strProc.ParamByName('ABBR').AsString := 'ZZZTOP';
cds.Open;