我也遇到了该问题,在客户端点击了ApplyUpdate(0)三次后,应用服务器程序就死机了,我是照李维老师的那本系统篇的例子做的。
服务器端:有一个窗口,上面有一个DBGRID,是显示客户端传过来的要更新的数据,当客户端点击applyUpdate(0)三次后,这个表DBGRID就不会显示了,发生死机。
DBGRID的ClientDataset1的数据是直接在Provider的onUpdateData事件赋值的。
procedure TMySevenMultiSrv.sgUpdateSQLProviderUpdateData(Sender: TObject;
DataSet: TCustomClientDataSet);
var
iCount1,iCount2:integer;
begin
Form1.ClientDataSet1.Data:=DataSet.Data;
...
end;
按F8单步执行时,代码都是正常执行,但就是在窗口显示中,DBGRID会发生死机。真是弄不明白。
程序源代码如下:
---Server.pas
unit Server;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, DBClient, Grids, DBCtrls, DBGrids, ExtCtrls, ComCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
StringGrid1: TStringGrid;
ClientDataSet1: TClientDataSet;
DataSource1: TDataSource;
StatusBar1: TStatusBar;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
end.
--ServerDM.pas
unit ServerDM;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
Windows, Messages, SysUtils, Classes, ComServ, ComObj, VCLCom, DataBkr,
DBClient, ServerApp_TLB, StdVcl, Provider, DB, ADODB;
type
TMySevenMultiSrv = class(TRemoteDataModule, IMySevenMultiSrv)
ADOConnection1: TADOConnection;
ADOQuery1: TADOQuery;
sgUpdateSQLProvider: TDataSetProvider;
sgUpdateDataSetProvider: TDataSetProvider;
ADOQuery2: TADOQuery;
procedure ADOQuery2BeforePost(DataSet: TDataSet);
procedure ADOQuery2AfterPost(DataSet: TDataSet);
procedure sgUpdateSQLProviderUpdateData(Sender: TObject;
DataSet: TCustomClientDataSet);
private
{ Private declarations }
protected
class procedure UpdateRegistry(Register: Boolean;
const ClassID, ProgID: string);
override;
public
{ Public declarations }
end;
implementation
uses Server;
{$R *.DFM}
procedure TMySevenMultiSrv.ADOQuery2AfterPost(DataSet: TDataSet);
begin
Form1.StatusBar1.Panels[0].Text:='After Post被触发了!';
end;
procedure TMySevenMultiSrv.ADOQuery2BeforePost(DataSet: TDataSet);
begin
Form1.StatusBar1.Panels[1].Text:='Before Post被触发了!';
end;
procedure TMySevenMultiSrv.sgUpdateSQLProviderUpdateData(Sender: TObject;
DataSet: TCustomClientDataSet);
var
iCount1,iCount2:integer;
begin
Form1.ClientDataSet1.Active:=false;
Form1.ClientDataSet1.Data:=DataSet.Data;
Form1.ClientDataSet1.Active:=True;
Form1.StringGrid1.ColCount:=0;
Form1.StringGrid1.RowCount:=0;
Form1.StringGrid1.ColCount:=Dataset.FieldCount;
Form1.StringGrid1.RowCount:=Dataset.RecordCount;
for icount1 := 0 to Dataset.FieldCount - 1do
Form1.StringGrid1.Cells[iCount1,0]:=Dataset.Fields[iCount1].FieldName;
for iCount1 := 0 to Dataset.RecordCount-1do
begin
for iCount2 := 0 to DataSet.FieldCount - 1do
begin
if (pfInUpdate in DataSet.Fields[iCount2].ProviderFlags) then
Form1.StringGrid1.Cells[iCount2,iCount1+1]:=Form1.StringGrid1.Cells[iCount2,iCount1+1]+
' pfInUpdate';
if (pfInWhere in DataSet.Fields[iCount2].ProviderFlags) then
Form1.StringGrid1.Cells[iCount2,iCount1+1]:=Form1.StringGrid1.Cells[iCount2,iCount1+1]+
' pfInWhere';
if (pfInKey in Dataset.Fields[icount2].ProviderFlags) then
Form1.StringGrid1.Cells[iCount2,iCount1+1]:=Form1.StringGrid1.Cells[iCount2,iCount1+1]+
' pfInKey';
if (pfHidden in Dataset.Fields[iCount2].ProviderFlags) then
Form1.StringGrid1.Cells[iCount2,iCount1+1]:=Form1.StringGrid1.Cells[iCount2,iCount1+1]+
' pfHidden';
end;
end;
end;
class procedure TMySevenMultiSrv.UpdateRegistry(Register: Boolean;
const ClassID, ProgID: string);
begin
if Register then
begin
inherited UpdateRegistry(Register, ClassID, ProgID);
EnableSocketTransport(ClassID);
EnableWebTransport(ClassID);
RegisterPooled(ClassID,10,10,True);
end else
begin
DisableSocketTransport(ClassID);
DisableWebTransport(ClassID);
UnRegisterPooled(ClassID);
inherited UpdateRegistry(Register, ClassID, ProgID);
end;
end;
initialization
TComponentFactory.Create(ComServer, TMySevenMultiSrv,
Class_MySevenMultiSrv, ciMultiInstance, tmApartment);
end.
--客户端代码:
unit Client;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, DBCGrids, ExtCtrls, DBCtrls, Db, DBClient, MConnect, Mask;
type
TForm2 = class(TForm)
DCOMConnection1: TDCOMConnection;
ClientDataSet1: TClientDataSet;
DBNavigator1: TDBNavigator;
Button1: TButton;
Edit1: TEdit;
DBCtrlGrid1: TDBCtrlGrid;
Label1: TLabel;
DBEdit1: TDBEdit;
DataSource1: TDataSource;
Label2: TLabel;
DBEdit2: TDBEdit;
Label3: TLabel;
DBEdit3: TDBEdit;
Label4: TLabel;
DBEdit4: TDBEdit;
Label5: TLabel;
DBEdit5: TDBEdit;
Label6: TLabel;
DBEdit6: TDBEdit;
Label7: TLabel;
DBEdit7: TDBEdit;
Label8: TLabel;
DBEdit8: TDBEdit;
Label9: TLabel;
DBEdit9: TDBEdit;
Label10: TLabel;
DBEdit10: TDBEdit;
Label11: TLabel;
DBEdit11: TDBEdit;
Button2: TButton;
ClientDataSet2: TClientDataSet;
Edit2: TEdit;
Button3: TButton;
ClientDataSet1customerID: TWideStringField;
ClientDataSet1CompanyName: TWideStringField;
ClientDataSet1contactName: TWideStringField;
ClientDataSet1ContactTitle: TWideStringField;
ClientDataSet1Address: TWideStringField;
ClientDataSet1City: TWideStringField;
ClientDataSet1Region: TWideStringField;
ClientDataSet1Postalcode: TWideStringField;
ClientDataSet1Country: TWideStringField;
ClientDataSet1phone: TWideStringField;
ClientDataSet1fax: TWideStringField;
procedure ClientDataSet1AfterPost(DataSet: TDataSet);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure ClientDataSet2AfterPost(DataSet: TDataSet);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.DFM}
procedure TForm2.ClientDataSet1AfterPost(DataSet: TDataSet);
begin
Edit1.Text := IntToStr(ClientDataSet1.ChangeCount);
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
ClientDataSet1.ApplyUpdates(0);
ClientDataSet1.Refresh;
end;
procedure TForm2.Button2Click(Sender: TObject);
begin
ClientDataSet2.ApplyUpdates(0);
// ClientDataSet2.Refresh;
end;
procedure TForm2.ClientDataSet2AfterPost(DataSet: TDataSet);
begin
Edit2.Text := IntToStr(ClientDataSet2.ChangeCount);
end;
procedure TForm2.Button3Click(Sender: TObject);
begin
if DataSource1.DataSet = ClientDataSet1 then
DataSource1.DataSet := ClientDataSet2
else
DataSource1.DataSet := ClientDataSet1;
end;
end.