当前位置:主页>销售管理软件> 列表

ClientDataSet 怪问题,请高手帮忙!!!! 找用友财务软件下载

仓库管理软件版1楼: 三层结构,用ClientDataSet执行查询数据数据操作,第一次、第二次都成功(单击同一个Button,执行相同的SQL语句),可是第三次(单击同一个Button,执行相同的SQL语句)或第四次就会死机,请问这是怎么回事呀?请高手赐教!!!

2楼: 数据缓存没有更新或状态值未归位 如服装店销售管理软件

3楼: 间隔时间太短了吧?

4楼: 很可能和你的连接机制和线程模型有关。
尽量要用无状态连接机制。

5楼: 关注此问题,我用同样技术做的三层,应用服务器大约每运行一天多,客户端就无法连接上

6楼: 8成服务器端没释放!要是一天查个几万次,每次1K,也就当了。。。

仓库管理软件版7楼: 如何查询的呢,具体一点说出来.

8楼: 中间层要做成无状态的。
可以使用ADO或者dbExpress连接,操作的时候应该使用这样的方式:
obj: IMyComObj;

obj := coMyComObj.CreateRemote(''ServerPC'');
try
ClientDataSet.Date := obj.AS_GetRecords(...);
finally
obj := nil;
end;

保证每次调用完了以后都正确释放。

9楼: 帮顶!

http://www.source520.com

站长开发推广同盟 站长朋友的终极驿站
同时拥有海量源码电子经典书籍下载

http://www.source520.com/search/search.asp

"编程.站长"论坛搜索引擎-----为中国站长注入动力!

10楼: 用COM+先取得数据,再送给客户端.

11楼: 采用無狀態模式來實現。

12楼: 帮顶!

╭=========================================╮

80G海量源代码,控件,书籍全免费狂下不停!

http://www.source520.com

╰=========================================╯ 如免费局域网管理软件

13楼: 我是在客户端写的SQL语句,服务端用一 DataSetProvider+Query 建立连接,客户端给ClientDataSet的Commandtext赋SQL语句,然后ClientDataSet.open;

to huangsong:
请问如何“数据缓存没有更新或状态值未归位 ”?谢谢!!


to happycyp:
请问怎样使用”无状态连接机制“连接?谢谢!!

to bbgsgs:
请问服务器端如何释放? 谢谢!!

to delphisuccess:
请问如何实现无状态模式?谢谢!!

请赐教!!!

仓库管理软件版14楼: 无状态连接,就是一个服务器端的进程不需要释放和重新建立就可以反复的为不通的客户端请求服务,即只有采用了无状态连接方式才可以使用Pooling(池)来极大的提高软件的运行效率并同事降低中间件服务器的资源占用。
有状态连接就是服务器端必须保存客户端的状态信息,以备下一次同一个客户端连接进来以后可以进行下一步的操作,比如客户端打开了一个什么表,下一次可能会对这个表进行更新,这个过程中服务器端必须记住表的名字和数据库的连接信息。否则的话下一次进行更新(ApplyUpdate)的时候服务器就不知道要对哪个表进行操作了。[red][b]客户端连接到服务端之后,服务端会初始化一个新的服务进程来为客户端服务,在客户端做完所有操作之前不释放,客户端完成所有操作只有再释放。[/b][/red]
无状态连接是相对于有状态连接而言的,即所有的信息都保存在客户端。客户端每次连接到服务器端可以不用开一个新的服务进程,只要连接到一个现有的服务进程就可以进行操作了。服务进程在服务结束以后也不释放,而是返回到池中等待下一个请求。释放由中间件服务器容器的机制决定。多长时间没有请求释放或者最少维持多少个进程不释放等等。客户端每次请求服务器服务的时候,都尽快释放,下一次再请求就可以了,比如读取数据完了以后关闭中间件连接,更新数据的时候重新打开连接进行操作。

15楼: 帮顶!

╭=========================================╮

80G海量源代码,控件,书籍全免费狂下不停!

http://www.source520.com

╰=========================================╯

16楼: to 硕鼠:
谢谢!!请问如何建立无状态连接和有状态连接?!!!元宵节快乐!!!

17楼: 建立没有区别,关键是释放。
有状态对象是在程序开始的时候建立连接,程序结束的时候释放。
无状态对象是在需要进行数据操作的时候建立连接,操作结束后马上释放,每次建立的连接只处理一个或很少的几个连贯的数据操作。每次需要进行数据操作就重新建立连接。

18楼: 比如我想按无状态的模式执行,打个比方,现在想输入一张单据B,而输入这张单据,需要先打开另一张单据A先读取些资料,那在输入单据A之前,一定要先查询一次的,那查询完后,用户开始输入的时候,是不是要先把连接释放,然后在保存的时候,再重新连接?

19楼: 对的,打开读,关闭,修改然后再打开连接更新。

20楼: 这说的关闭,是指把SockedConnection.Connected设为False吗? 如果是的话,那每次重新连接,会不会要额外的连接时间,因为在输入一张单据的过程中,可能会要查询基本资料很多次(10多次都正常),比如要选取客户,明细表中的物料等,这样的操作,也要每次查询完就关闭连接吗?

仓库管理软件版21楼: 如果没有人机交互的过程就叫一次。可以一起执行。
另外就是在本地建立一定的数据缓冲。把一些数据存放在本地,定时和服务器进行同步。
三层应用本身就是一种以时间换空间的方法。
即每一个用户的速度都降低一点,但是可以连接的用户数极大的提好。而且安全性方面和可维护性方面也有极大的提高。
连接虽然比较费时间,但是创建进程、连接数据库的时间可以通过池处理来节省。所以一般情况下速度可能会比直接连接数据库还要快一些。

22楼: 我也遇到了该问题,在客户端点击了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 - 1 do
Form1.StringGrid1.Cells[iCount1,0]:=Dataset.Fields[iCount1].FieldName;

for iCount1 := 0 to Dataset.RecordCount-1 do
begin
for iCount2 := 0 to DataSet.FieldCount - 1 do
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. 如用友财务软件下载

23楼: 请问有状态连接是不是指在程序打开时就把SockedConnection.Connected设为true,程序退出时才关闭,状态连接是不是指每次查询数据时都要将SockedConnection.Connected设为true,查完后再设为False?谢谢!!
请问连接池是怎么建立的?谢谢!!!!!!

24楼: 顶

25楼: 如果是用SocketConnection ,那么Scksrv.exe不能设为服务启动模式,应以程序运行方式启动!

26楼: 其实应该在服务器端来进行对数据库的操作才是正道!
尽量少用或不用CLIENTDATASET来直接下达SQL指令。必须要用的时候也要尽早释放链接。

27楼: 三层死机一般有几种原因:
一、服务器的中间层没写好
二、如果在多cpu的服务器中用了scktsrvr.exe,需要注意scktsrvr.exe的版本
看看我们的例子吧www.szmax.net/webpush-8.htm

仓库管理软件版28楼: ding[^]

29楼: COM+查询到数据后,使用Variant回传给ClientDataSet,然后关闭查询。