【发布时间】:2012-10-22 13:52:21
【问题描述】:
这个问题直接关系到我的Previous Question。
我需要从包中包含的 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
执行设计时配置的函数
function TKPSnapMethods.getCDS_Data3: OLEVariant;
begin
self.ClientDataSet1.Open;
result:= self.ClientDataSet1.Data;
self.SQLConnection1.Close;
end;
执行运行时配置的函数 这是返回空 ClientDataSet 的代码。目标是连接碎片,设置参数值,打开CDS并返回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;
再次,我必须承认我是 Delphi 语言的新手。我搜索了 google、code.google、Embarcadero Developer Network 和 DBExpress 文档,但均无济于事。 我只是不明白为什么设计时和运行时之间会有差异。
【问题讨论】:
-
请不要在您的问题主题中包含标签信息;这里的标记系统设计得非常好,无需帮助即可工作。此外,没有必要在您的问题中提供任何信息;即使我们可能有听力障碍,这里的阅读理解力也往往非常高,而且全部大写的文本更难阅读(而且很烦人)。没有它,我们也会看到您的问题。谢谢。
-
你的问题很不清楚。您说设计时有效,但运行时无效,但客户端
Button1Click处理程序中的代码显示了两个完全独立的函数调用(getCDS_Data2('TESTTH1)和getCDS_Data3(无参数))并说其中一个有效,但您只显示getCDS_Data2的代码。当你不给我们比较代码时,很难比较它们并说明为什么一个有效而另一个无效。 -
我已更新标题以删除标签和以大写字母开头的单词。包含 getCDS_Data3 的代码,也许您只是忽略了它。你知道为什么该函数会在设计时而不是运行时工作吗?谢谢
-
你是对的。我忽略了它。
getCDS_Data2的代码大约有四十行代码,而getCDS_Data3是三行;我想我希望它们更相似,因为您希望我们解释不同的行为。你能解释一下这些是如何比较的吗? (第一个是大约 13 倍的代码,这显然意味着每三行应该是等效的。) -
函数如此大不相同的原因是函数 getCDS_Data3 从提供的设计时代码中获取其组件设置,而函数 getCDS_Data2 在运行时创建和设置其组件。我需要在运行时执行存储过程,因为对于我需要执行的每个存储过程,在数据模块上放置一个组件效率不高。对于组件在运行时与设计时为何表现不同的任何意见,我将不胜感激。谢谢
标签: delphi oracle11g cursor delphi-xe2 dbexpress