发表于:
2009-11-10 20:49:44
大家晚上好: 我现在看李维写的《Delphi 5.x 分布式多层应用系统篇》,在运行5-1节示例代码的时候。 客户端的代码运行到红色字体的时候就会出错,错误代码是:“CDSBash Cannot perform this operation on a closed dataset”!请大家帮忙看一下,为什么会出这样的错?CDSBash 的属性FetchOnDemand 已设为False. PacketRecords 设为10。 关于Delphi 三层无状态分段取数据。如果大家有什么好的想法或建议,可以告诉小弟! 在此先感谢一下各位了。
客户端代码如下: unit main;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DB, DBClient, MConnect, Grids, Wwdbigrd, Wwdbgrid, StdCtrls, Buttons, Mask, DBCtrls, SConnect, ExtCtrls;
type TForm1 = class(TForm) DataSource1: TDataSource; wwDBGrid1: TwwDBGrid; Label1: TLabel; Edit1: TEdit; SpeedButton1: TSpeedButton; SpeedButton2: TSpeedButton; DBNavigator1: TDBNavigator; SpeedButton3: TSpeedButton; CDSBash: TClientDataSet; SocketConnection1: TSocketConnection; CDSBashsh01: TStringField; CDSBashsh02: TStringField; CDSBashsh03: TStringField; CDSBashsh04: TStringField; CDSBashsh05: TStringField; CDSBashsh06: TStringField; CDSBashsh07: TStringField; CDSBashsh08: TBCDField; CDSBashsh09: TStringField; CDSBashsh10: TBCDField; CDSBashsh11: TBCDField; CDSBashsh12: TBCDField; CDSBashsh13: TBCDField; CDSBashsh14: TStringField; CDSBashsh15: TStringField; CDSBashsh16: TBCDField; CDSBashsh17: TBCDField; procedure FormDeactivate(Sender: TObject); procedure SpeedButton1Click(Sender: TObject); procedure CDSBashBeforeGetRecords(Sender: TObject; var OwnerData: OleVariant); procedure SpeedButton2Click(Sender: TObject); procedure CDSBashReconcileError(DataSet: TCustomClientDataSet; E: EReconcileError; UpdateKind: TUpdateKind; var Action: TReconcileAction); procedure FormActivate(Sender: TObject); procedure CDSBashAfterGetRecords(Sender: TObject; var OwnerData: OleVariant); procedure SpeedButton3Click(Sender: TObject); private { Private declarations } vOwnerData :OleVariant; v2OwnerData :OleVariant; bTrueEOF :Boolean; public { Public declarations } function GetKeyFieldValue(Sender:Tobject):OleVariant; end;
var Form1: TForm1;
implementation
uses Unit1;
{$R *.dfm}
procedure TForm1.FormDeactivate(Sender: TObject); begin SocketConnection1.Connected :=false; CDSBash.Active :=false; end;
procedure TForm1.SpeedButton1Click(Sender: TObject); var abk :TBookMark; begin try if (not bTrueEOF) then begin try abk :=CDSBash.GetBookmark; if (CDSBash.GetNextPacket < CDSBash.PacketRecords ) then bTrueEOF :=True; CDSBash.Last; vOwnerData :=CDSBash.fieldbyname('sh01').AsString; CDSBash.GotoBookmark(aBK); CDSBash.Next; finally CDSBash.FreeBookmark(aBK); end; end; except on Exception do; end; Edit1.Text :=IntToStr(CDSBash.RecordCount); end;
procedure TForm1.CDSBashBeforeGetRecords(Sender: TObject; var OwnerData: OleVariant); begin if ((VarIsEmpty(vOwnerData)) or (VarIsNull(vOwnerData))) then vOwnerData :=GetKeyFieldValue(Sender);
OwnerData :=vOwnerData; end;
procedure TForm1.SpeedButton2Click(Sender: TObject); begin CDSBash.ApplyUpdates(0); end;
procedure TForm1.CDSBashReconcileError(DataSet: TCustomClientDataSet; E: EReconcileError; UpdateKind: TUpdateKind; var Action: TReconcileAction); begin //HandleReconcileError(CDSBash, UpdateKind, E); if E.ErrorCode <>0 then begin messagedlg('更新失败'+#13#10+E.Message,mtInformation,[mbOk],0); end; end;
procedure TForm1.FormActivate(Sender: TObject); begin SocketConnection1.Connected :=true; CDSBash.Active :=true; Edit1.Text :=IntToStr(CDSBash.RecordCount); end;
procedure TForm1.CDSBashAfterGetRecords(Sender: TObject; var OwnerData: OleVariant); //var // CurRecord:TBookMark; // AA:STRING; begin { try with Sender as TClientDataSet do begin CurRecord :=GetBookmark; try last; AA := CDSBash.FieldByName('sh01').value; vOwnerData :=CDSBash.FieldByName('sh01').value; GotoBookmark(CurRecord); finally FreeBookMark(CurRecord); end; end; except on Exception do; end; } end;
procedure TForm1.SpeedButton3Click(Sender: TObject); begin CDSBash.Refresh; end;
function TForm1.GetKeyFieldValue(Sender: Tobject): OleVariant; var CurRecord: TBookMark; begin try with Sender as TClientDataSet do begin CurRecord :=GetBookmark; try last; Result :=FieldbyName('sh01').Value; GotoBookMark(CurRecord); finally FreeBookMark(CurRecord); end; end; except on Exception do; end; end;
end. ************************************** 服务器端的代码是如下: unit RemoteData;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses Windows, Messages, SysUtils, Classes, ComServ, ComObj, VCLCom, DataBkr, DBClient, pBash_TLB, StdVcl, DB, ADODB, Provider;
type Ttestbash = class(TRemoteDataModule, Itestbash) ADObash: TADOQuery; DSPBash: TDataSetProvider; ADOConnection1: TADOConnection; ADObashsh01: TStringField; ADObashsh02: TStringField; ADObashsh03: TStringField; ADObashsh04: TStringField; ADObashsh05: TStringField; ADObashsh06: TStringField; ADObashsh07: TStringField; ADObashsh08: TBCDField; ADObashsh09: TStringField; ADObashsh10: TBCDField; ADObashsh11: TBCDField; ADObashsh12: TBCDField; ADObashsh13: TBCDField; ADObashsh14: TStringField; ADObashsh15: TStringField; ADObashsh16: TBCDField; ADObashsh17: TBCDField; procedure DSPBashBeforeGetRecords(Sender: TObject; var OwnerData: OleVariant); procedure RemoteDataModuleCreate(Sender: TObject); procedure RemoteDataModuleDestroy(Sender: TObject); private { Private declarations } protected class procedure UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); override; public { Public declarations } end;
implementation
{$R *.DFM}
class procedure Ttestbash.UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); begin if Register then begin inherited UpdateRegistry(Register, ClassID, ProgID); EnableSocketTransport(ClassID); EnableWebTransport(ClassID); end else begin DisableSocketTransport(ClassID); DisableWebTransport(ClassID); inherited UpdateRegistry(Register, ClassID, ProgID); end; end;
procedure Ttestbash.DSPBashBeforeGetRecords(Sender: TObject; var OwnerData: OleVariant); begin with Sender as TDataSetProvider do begin DataSet.Open; DataSet.Locate('sh01',OwnerData,[]); DataSet.Next; end; end;
procedure Ttestbash.RemoteDataModuleCreate(Sender: TObject); begin ADOConnection1.Connected := True; ADOBash.Active := True; end;
procedure Ttestbash.RemoteDataModuleDestroy(Sender: TObject); begin ADOConnection1.Connected := false; ADOBash.Active := false; end;
initialization TComponentFactory.Create(ComServer, Ttestbash, Class_testbash, ciMultiInstance, tmApartment); end. |