刚学Delphi,一箩筐问题(三层的),分很容易赚 (100分)

  • 主题发起人 主题发起人 hsb0307
  • 开始时间 开始时间
H

hsb0307

Unregistered / Unconfirmed
GUEST, unregistred user!
初学者的苦恼:
1、主从表更新:李维的书中在AppServer端将主从表设置好,在客户端进行连接,这样岂不是每对主从表都要在中间层设置。如果有一百对主从表,在中间层设置可就麻烦了。
2、TClientDataset(缩写为cds)能不能发带参数的SQL语句,如果能,参数用什么方式发过去,TDatasetProvider(缩写为dsp)什么事件接收,最好给个代码参考一下,给个处理流程也行。
3、看这里也有分送: http://www.delphibbs.com/delphibbs/dispq.asp?lid=2285566
4、看这里:http://www.playicq.com/dispdocnew.php?id=4602
5、三层程序中,怎样使用存储过程?
请问在服务器端还需要怎样处理?
 
可以参数,用存储过程就行带
 
我也很菜,帮你顶一下啦
 
to zhijl1027:
非常感谢你的回答,能不能借用你的宝贵时间,给我上上课:
问一下,TClientDataset(缩写为cds)发带参数的SQL语句,在服务器端和客户端的处理流程。
 
我也很菜,帮你顶一下啦 [:D]
 
这个问题跟各位一起讨论一下……我弄了一个,但还没试过用参数。
但我想可以这样:
当cds发送请求时(datarequest),把参数和参数的值一起附载到SQL里边发送给应用服务器,应用服务器收到时进行解释(自己写代码):
参数一般写法:
"select * from table where writedate between :begin
date and :enddate"
都是以冒号+参数名,然后参数值可以紧跟在这个语句后面写成:
"select * from table where writedate between :begin
date and :enddate{'+DateToStr(Date1)+','+DateToStr(Date2)+'}"
“{}”中就是参数值列表,一一对应,然后将这个SQL一起传给应用服务器处理(当然不能直接执行),应用服务器端应该有一个数据集控件(这里以Query为例):
function TD_4Server.Provider1DataRequest(Sender: TObject;
Input: OleVariant): OleVariant;
var
SQLStr,TmpStr,CurParm:string;
HaveParam:Boolean;
ParPos,ParCnt:Integer;
begin
if Input='' then
Exit;
ParCnt:=0;//参数个数
SQLStr:=UpperCase(Input);
HaveParam:=Pos(':',SQLStr)>0;
{然后循环取出参数}
TmpStr:=Trim(Copy(SQLStr,Pos('{',SQLStr)+1,Length(SQLStr)));//把{}中的参数值列表取出来,可能不是很精确,仅是个例子而已
SQLStr:=Delete(SQLStr,Pos('{',SQLStr),Length(SQLStr));//还原SQL
Delete(TmpStr,Length(TmpStr),1);//删除最后一个"}"
((Sender as TProvider).DataSet as TQuery).Close;
((Sender as TProvider).DataSet as TQuery).SQL.Clear;
((Sender as TProvider).DataSet as TQuery).SQL.Add(SQLStr);
//参数
((Sender as TProvider).DataSet as TQuery).Params.Clear;
ParPos:=Pos(',',TmpStr);
while ParPos>0do
begin
CurParm:=Copy(TmpStr,1,ParPos-1);
((Sender as TProvider).DataSet as TQuery).Params[ParCnt].Value:=CurParm;//这里注意参数类型
Delete(TmpStr,1,ParPos);
Inc(ParCnt);
end;
((Sender as TProvider).DataSet as TQuery).Params[ParCnt].Value:=TmpStr;
((Sender as TProvider).DataSet as TQuery).Open;
end;
//此例子仅供参考
 
参数就在TClientDataSet.Params里设置呗,直接一同传给了datasetprovider,不需要事件处理的。当然你也可以另外自己定义接口函数来实现,这就是完全两回事了。[:)]
 
to hongxing_dl:
非常感谢,你的这个方案不错.
客户端获取数据的方法有多种,比如:
1、cds.comandtext
2、cds.DataRequest
3、cds.FetchOnDemand:=False和PacketCount:=1到n
我问的问题里只是用的第一种方法,大家能不能解释一下,什么情况下用那种方法。
请问:在SQL语句中有参数的情况是不是常用第二种方法,用cds.DataRequest,先生成一个变体数组Data:=VarArrayOf(带参数的SQL语句,参数值一,参数值二,参数值三),用cds.DataRequest将此变体数组传到AppServer,并由其OnDataRequest事件分离出带参数的SQL语句和参数,执行。
 
to chengsa:
请问:参数在TClientDataSet.Params里设置,是不是AppServer端的数据集必须先设置好带参数的SQL语句。
如果是这样,如果AppServer端有一百个带参数的查询,在中间层设置可就麻烦了。
 
我在服务器端设置DataSetProvider的option属性中poallowcommandtext的为真。
在客户端
ClientDataSet1.CommandText:='select DepartId,DepartName,Status from tblDepart where Status='+''''+trim(edit1.Text)+''''
没有进行参数传递。
 
我没有真正试过,但是,datasetprovider不一定需要倚赖一个dataset来提供数据的。它可以自己生成sql语句,自己向数据库服务器发送。
在这个事实上,我的理解,commandtext是和params搭配使用的,比如
commandtext := 'select * from sno = :sno'
params.parambyname('sno').AsIntger := 2;
这样用,那么sql语句还是从客户端发送过去的。
可以实际试试呀,还有delphi的帮助看看。
 
嗯,我试过了,参数和sql是一起发送过去的。[:D]
 
可以,但DataProvide组件的AllowCommandText属性必须设为True
 
to yu_ting: 这个是显然的啦,不用说了嘛。[8D]
 
to chengsa:
是我搞错了,
cdsCommon.Close;
cdsCommon.CommandText:=Edit6.Text;//Select * from [sdDept] Where = :DeptName
cdsCommon.Params.ParamByName('DeptName').AsString:=Edit7.Text;
cdsCommon.Open;
//Select * from [sdDept] Where = :DeptName应为:
//Select * from [sdDept] Where [DeptName]= :DeptName
 
请大家看看另外几个问题:1,3,4
请问:在SQL语句中有参数的情况是不是常用cds.DataRequest,先生成一个变体数组Data:=VarArrayOf(带参数的SQL语句,参数值一,参数值二,参数值三),用cds.DataRequest将此变体数组传到AppServer,并由其OnDataRequest事件分离出带参数的SQL语句和参数,执行。
 
好问题,在这里学习
 
别刚回答的,我copy过来,大家学习:
function THiteker.FGetFeePay
(
const psProcName : WideString;
//存储过程名称
psParam : OleVariant;
// 传入参数列表
out poParam : OleVariant // 传出参数列表
): OleVariant;
var
spExec : TStoredProc;
iLoop : Integer;
iParamCount1, iParamCount2 : Integer;
//传入参数个数,传出参数个数(不含po_iResult)
sErrMsg : String;
begin
Result := -1;
spExec := TStoredProc.Create(application);
Try
Try
iParamCount1 := VarArrayHighBound(psParam, 1);
With spExecdo
begin
Close;
DatabaseName := 'dbHiteker';
StoredProcName := UpperCase(psProcName);
Prepare;
iParamCount2 := ParamCount - iParamCount1 - 2;
poParam := VarArrayCreate([0, iParamCount2-1], VarOleStr);
for iLoop := 0 to iParamCount1do
begin
Params[iLoop].AsString := psParam[iLoop];
end;

//
ExecProc;
For iLoop := 0 To iParamCount2-1do
begin
poParam[iLoop] := Trim(Params[iParamCount1 + 1 + iLoop].AsString);
end;
sErrMsg := Params[iParamCount1 + iParamCount2].AsString;
//提示信息
Result := Params[iParamCount1 + iParamCount2 + 1].AsInteger;
//返回值
end;
Except
on E:Exceptiondo
begin
sErrMsg := '《' + psProcName + '》执行失败〖' + E.Message + '〗';
end;
end;
Finally
spExec.Free;
end;
end;
 
Tclientdataset的mastersource设为主表,再设置一下masterfields就行了。
 
to Yank;
关键是:在客户端设置从表TClientdataset的mastersource为主表,再设置一下masterfields之前,要在服务器端先设好主从关系,如果服务器端没设好主从关系怎么办?
另,大家看看这里:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2242451
 
后退
顶部