分享

delphi三层无状态分段取数据

 quasiceo 2017-03-10
发表于: 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.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多