客户端://获取数据
var
SQLStr1, SQLStr1:String;
Index2Tem : String;
begin
....
Index2Tem := 'StudentNo'; //建立主从表的关键字段
SQLStr1 := 'select * from student';
SQLStr2 := 'select * from choose'; MDForm.SQLStr1 := SQLStr1;
MDForm.SQLStr2 := SQLStr2;
MDForm.CDSMaster.Active := False; //主表学生ClientDataset
MDForm.CDSDetail.Active := False; //从表选择ClientDataset 一个学生可以选择多门课程
MDForm.CDSMaster.CommandText := SQLStr1;
MDForm.CDSDetail.CommandText := SQLStr2; MDForm.CDSMaster.Execute;
MDForm.CDSMaster.Active := True; MDForm.CDSDetail.IndexFieldNames := Index2Tem;
MDForm.CDSDetail.MasterFields := Index2Tem; //建立关联的StudentNo字段
MDForm.CDSDetail.Execute;
MDForm.CDSDetail.Active := True;
.....
end;//更新数据
procedure TStandMDForm.BitBtnApplyClick(Sender: TObject);
var
vDeltaArray : OleVariant;
vProviderArray : OleVariant;
vCDSArray: array[0..1] of TClientDataset;
begin
vCDSArray[0] := CDSMaster;
vCDSArray[1] := CDSDetail;
vDeltaArray := RetrieveDeltas(vCDSArray); //获取变化数据的数组ClientDataset.Delta
vProviderArray := RetrieveProviders(vCDSArray); //获取提供者的数组TDataSetProvider
DataModule1.SCMaster.AppServer.ApplyUpdatesMD(vDeltaArray, vProviderArray, SQLStr1, SQLStr2);
ReconcileDeltas(vCDSArray, vDeltaArray);
end;
服务器端:
//更新主从表
procedure Tco_Server.ApplyUpdatesMD(var vDeltaArray, vProviderArray: OleVariant;
const SQLStrM, SQLStrD: WideString);
begin
ADQMaster.Close; //主表ADOQuery
ADQMaster.SQL.Clear;
ADQMaster.SQL.Add('select * from student'); //问题1 ADQDetail.Close; //从表ADOQuery
ADQDetail.SQL.Clear;
ADQDetail.SQL.Add('select * from choose'); //问题2 CDSApplyUpdates(ADOConnection1, vDeltaArray, vProviderArray, False);
//真正的更新是用
//Delta := IAppServerDisp(IDispatch(AProvider[0])).AS_ApplyUpdates(AProvider[1], Delta, 0, ErrCount, OwnerData);
//
end;问题:当把问题1处和问题2处的SQL语句在设计时直接填入主从表Query的SQL中,更新一点问题都没有。可是当用这种运行时动态设置SQL语句的方法会出错“mismatch in datapacket”。请指教,现次感谢!
var
SQLStr1, SQLStr1:String;
Index2Tem : String;
begin
....
Index2Tem := 'StudentNo'; //建立主从表的关键字段
SQLStr1 := 'select * from student';
SQLStr2 := 'select * from choose'; MDForm.SQLStr1 := SQLStr1;
MDForm.SQLStr2 := SQLStr2;
MDForm.CDSMaster.Active := False; //主表学生ClientDataset
MDForm.CDSDetail.Active := False; //从表选择ClientDataset 一个学生可以选择多门课程
MDForm.CDSMaster.CommandText := SQLStr1;
MDForm.CDSDetail.CommandText := SQLStr2; MDForm.CDSMaster.Execute;
MDForm.CDSMaster.Active := True; MDForm.CDSDetail.IndexFieldNames := Index2Tem;
MDForm.CDSDetail.MasterFields := Index2Tem; //建立关联的StudentNo字段
MDForm.CDSDetail.Execute;
MDForm.CDSDetail.Active := True;
.....
end;//更新数据
procedure TStandMDForm.BitBtnApplyClick(Sender: TObject);
var
vDeltaArray : OleVariant;
vProviderArray : OleVariant;
vCDSArray: array[0..1] of TClientDataset;
begin
vCDSArray[0] := CDSMaster;
vCDSArray[1] := CDSDetail;
vDeltaArray := RetrieveDeltas(vCDSArray); //获取变化数据的数组ClientDataset.Delta
vProviderArray := RetrieveProviders(vCDSArray); //获取提供者的数组TDataSetProvider
DataModule1.SCMaster.AppServer.ApplyUpdatesMD(vDeltaArray, vProviderArray, SQLStr1, SQLStr2);
ReconcileDeltas(vCDSArray, vDeltaArray);
end;
服务器端:
//更新主从表
procedure Tco_Server.ApplyUpdatesMD(var vDeltaArray, vProviderArray: OleVariant;
const SQLStrM, SQLStrD: WideString);
begin
ADQMaster.Close; //主表ADOQuery
ADQMaster.SQL.Clear;
ADQMaster.SQL.Add('select * from student'); //问题1 ADQDetail.Close; //从表ADOQuery
ADQDetail.SQL.Clear;
ADQDetail.SQL.Add('select * from choose'); //问题2 CDSApplyUpdates(ADOConnection1, vDeltaArray, vProviderArray, False);
//真正的更新是用
//Delta := IAppServerDisp(IDispatch(AProvider[0])).AS_ApplyUpdates(AProvider[1], Delta, 0, ErrCount, OwnerData);
//
end;问题:当把问题1处和问题2处的SQL语句在设计时直接填入主从表Query的SQL中,更新一点问题都没有。可是当用这种运行时动态设置SQL语句的方法会出错“mismatch in datapacket”。请指教,现次感谢!
vCDSArray[0] := CDSMaster; //主表ClientDataset
vCDSArray[1] := CDSDetail; //从表ClientDatasetDataModule1.SCMaster.AppServer.ApplyUpdatesMD(vDeltaArray, vProviderArray, SQLStr1, SQLStr2);这句是调服务器的更新方法。
但在更新时动态将SQL语句写入主从表ADOQuery.SQL中,就出现“mismatch in datapacket”错误。
ADOConnection1.BeginTrans;
try
ADQMaster.Close;
ADQMaster.SQL.Clear;
ADQMaster.SQL.Add(SQLStrM);
if not VarIsNull(MasterVar) then //主表
begin
MasterVar := DSPMaster.ApplyUpdates(MasterVar, 0, ErrCount);
if ErrCount > 0 then
SysUtils.Abort; //这将产生回滚
end; ADQDetail.Close;
ADQDetail.SQL.Clear;
ADQDetail.SQL.Add(SQLStrD);
if not VarIsNull(DetailVar) then //从表
begin
DetailVar := DSPDetail.ApplyUpdates(DetailVar, 0, ErrCount);
if ErrCount > 0 then
SysUtils.Abort; //这将产生回滚
end;
ADOConnection1.CommitTrans;
except
ADOConnection1.RollbackTrans;
end;如果有这种,就没有问题!
按该书的第一种方法还可以,可是用二种方法(是对第一种方法的重构)时就不行了。
ADQMaster.Close;
ADQMaster.SQL.Clear;
ADQMaster.SQL.Add(SQLStrM); ADQDetail.Close;
ADQDetail.SQL.Clear;
ADQDetail.SQL.Add(SQLStrD);
获取数据和更新数据。
cds_detail.close;
cds_detaili.commmandText='select * from Order_Detail_Table where OrderId='''+
cds_master.FieldByName('OrderId').AsString+'''';
cds_detaili.open;//本人觉得这样很方便的,速度也还不错,代码一般都放在主表网格当前行改变的事件上的