一个EXE文件中FORM太多怎么办,TDATABASE可以作为参数传递到DLL中吗?(270分)

  • 主题发起人 六窍通
  • 开始时间
各位兄弟,Delphi的方法我试用了,在Delphi3+M$ SQL Server 6.5,
Delphi3+Oracle7都不行,我不想再试其它的数据库了。
 
我用D3+SQL Server 6.5 作过一个项目,每个模块都有100个以上的Form,
1.采用动态Form创建
2.采用Form继承
3.创建TMyTable和TMyQuery控件,放入所有数据库通用操作

通过上述三种方法,虽然EXE文件有4M之多,但在486/66 20M内存上速度还可以



 
各位好,在此感谢各位的支持,有这么多朋友对这个问题感兴趣,十分高兴。
为此,本人决定向管理员申请,尽我所能再追加一定的分数。(希望可以)
讨论这个问题的意义在于这不是一个简单的是非问题,而是一个大的数据库
应用系统的设计思路,也是多模块商业化软件的开发方法 就如 delphi,
Randolph所说。
那么我们要讨论的可分为两个方面,一:策略,二:手段。
希望各位朋友能够继续进行深入的讨论。

DELPHI所说的主控+DLL 和我所想是一致的。但如果使用网络数据库,所用
手段不行。DELPHI可以试试:动态建立数据库别名。
我认为Randolph的方法可取。

无疑aimingoo给我们了一个新的考虑问题的角度,aimingoo可否说明一下
操作方法,这种方法在建立应用程序和维护时是否会耗费较多的精力?

 
我想从另一个方面来观察这个问题.

先整理一下:

已经提出的解决方法主要有:
A: 采用 mainApp+DLL 调用;
B: 采用TSession 或 Tdatabase来减少 database.Connect;
C: 动态建立Form
D: 动态调用Package

期望达到的效果为:
A: 降低分析和编程复杂度,加快EXE调用速度;
B: 减少 database.connect次数;
C: 减少 EXE启动速度;
D: 减少 EXE文件大小,也提高启动速度.

我认为,正如aimingoo所说,采用DLL并没有带来启动速度实质上的提高.
唯一有效的是可以先让用户看到主界面,把启动时间分成了两部分.
但它在软件工程上的效率是有目共睹的,所以是一个好办法.

动态创建组件或form,我认为这不是一个好办法.
从编程代价和带来的效率提高上来说,动态创建组件或form,需要程序员较高的
编程能力和逻辑思维水平,并且并不利于维护.谁也不能保证,3年或5年后你还在
这家公司,或者接替你的人具有和你同样的水平和习惯.
我宁愿使用Delphi本身提供的编程习惯.

使用Tsession传递,我认为是一个好方法.
如我在本版另一个问题的讨论中所说,一个Team的编程任务由系统程序员和应用程序
程序员共同完成.和动态创建组件不同,采用TSession,是可以由系统程序员开发
BasicForm和编程规则时制定的,应用程序编写时,如果采用继承Form的方法(我认为
是标准方法),时可以完全不管不顾的.这没有增加程序员的工作量和强度,也没有增
加维护代价.

事实上,编写数据库应用程序,制约速度的因素有如下几个:
1. Server端的效率.
2.client 端 Delphi 应用程序的效率
3.C/S 之间交换数据的效率.
从用户角度来说,感到速度慢,主要在于程序启动的速度和模块转换的速度.
以上涉及的都是有关于问题2的解决方法.

加快C/S交换数据速度等于减少传递量.
大部分的程序,都是实时更新表的,但PB里的数据窗口可以给我们以提示.
PB中,数据窗口只有在必要时才会去和数据库联系.

所以,在编程时,要尽量减少TransBegin...Commit的次数,比如只在修改完毕整个
表时才commit;只在涉及多个表更新时才commit等.
我认为,减少流量,是真正有效的,因为当Client增多时,影响效率的因素中Client
端实现上的问题会降到比较低的层次上去,主要是等待问题.
 
先说明一点,看了Randolph先生对我所提出的方法的质疑后,
今天上午特地回到单位,找了一个M$SQL Server 6.5得到如下
结论:
1.如果主EXE文件或者DLL之一没有使用Building with Runtime
Package,即编译成为了独立的执行文件或DLL,上面的示例
程序在调用DLL时仍然再次显示出对话框,要求输入密码,不过
程序还是可以正常执行下去,给我的印象是Delphi为DLL找到了
那个Database,不过需要重新建立一个连接。
2.在主EXE和DLL全部以Building with Runtime Package方式
编译,前面那个例子运行完全正常,Database Login对话框不
再出现。
我没有可以运行的Oracle Server,不能在Oracle上面测试。

Randolph先生是否没有将它编译成为Runtime Package?

此外还想说明一点,Runtime Package不知道各位有没有应用,
我认为还是很好用的。
综合使用Runtime Package与DLL对Form的加载时间还是有一些
提高,原因我认为和aimingoo所发现的Form Destroy后再次Create
速度较快一样,这是因为Windows应用程序并不是一次性加载进入
内存,而是根据需要进行加载。而主程序一旦启动完成,系统所需
要的主要Package和DLL均已载入,下次再载入功能模块时,就只有
区区几十K而已。而DLL动态创建Form又可以降低系统初始化时的时间,
将其分散开,所以给用户的感觉是速度有所提高。

当然,正如曹先生所讲,从根本上希望解决Server的效率问题,
主要的是流量。采用Multi-Tier技术才是根本之道。

 
六窍通, 问题的提出者,要求从自己的积分中对此问题追加70分。
这样可成了目前价值最高问题了。:)
 
分数提高当然更诱人,但是最好老兄补一个贴子,
说明到底想要什么样的答案?
 
对不起,上个贴子写了一半.

是要一个全套的解决方案,还是哪方面的技术细节,
以及这么多人的回答还欠缺哪方面?
 
确实如delphi老兄所说,用runtime package方式编译,
在ORACLE数据库下也是可以的。我试过了。其实用不用
TDatabase作参数都一样,反正Database Name是必须传
递的。
另外,使用Runtime Package和VC的Shared Dll一样。
也能够降低目标文件的大小,减小载入时间。在这方
面性能还是有提高的。
另一方面,需要提高数据库访问的速度。这倒没什么
好说的,无非是减少不必要的连接次数、数据查询能优
化就优化。
 
这个问题摆了一个月了,要么把要求详细提一遍,要么该收摊了。
 
用意,越长看起来越不方便。
 
1可以用动态form
2或者放到dll文件中去,如果需要方法可以email我
lishp@hongkong.com

^_^ waiting for you
 
老六!人民的呼声听见了没有?
 
收摊收摊
分账分账
快点快点
太长太长
!!!!!!!!

看这个post,我都要等到半个小时了啊!!!!!
 
大家好!
我想说一下TDataBase这个类, 它并不是一种数据源的
接口, 它并不象DataSet 和 DataSource 之间的那种联系,
它只是一个BDE DataBase的一个别名生成器, TTable, Tquery
等数据类访问数据库是直接与BDE联系, 并不访问TDataBase控件。

我们使用TTable、Tquery 等控件时,是通过DataBaseName进行
确认与哪个数据接口相连。
我们可以注意到!!!, 在没有TDataBase类的
程序中, 数据库的访问,可通过下列方式,将TTable 或 TQuery
设定为BDE中预制好的别名,我们照样可以Open或执行SQL,其中数据
库类型、用户名、口令等参数都是通过BDE Administrator或
SQL Explorer设定的。(如果DataBaseName为空, Delphi认为是默认
的Local数据库, 需要加路径)


我们试一试下面的方法就可以知道TDataBase是如何工作的
设定一个可以打开的TDataBase类 DB1 , 其中DataBaseName的
值为'B'
通过下列代码就可发现, TDataBase做了些什么,


session.GetAliasNames(listbox1.items); //将数据工作区中所有有效别名取出
Db1.Open ;
session.GetAliasNames(listbox2.items);
DB1.close ;
session.GetAliasNames(listbox3.items);
DB1.DatabaseName:='A';
Db1.Open ;
session.GetAliasNames(listbox4.items);

可以发现 在ListBox2中多了一个B ,listbox3 中B又没有了, listbox4 中多了一个A .

然后无论在Dll, 还是在Package 中, 对DB1数据库的访问, 只要将TTable,Tquery中
的DataBaseName设定为A. 若DataBaseName不存在于"别名列表"中,对TTable,Tquery的操作
都会触发异常.

正如dubhe所讲的那样, 传递只需要DatabaseName :string, TTable, Tquery对所操作
的数据库是通过DataBaseName来定位的. ( 注意sessionName要相同 , 对于不同的Session, Dll调用中
要另加sessionName参数 )

如果是通过TdataBase传递, Dll中可以预制一个TdataBase的变量, 不可以以直接控件方式加载,

例:
interface

Tform1 = class( Tform)
query1 : Tquery;
.
.//直接添加的控件)
.
.
procedure query1beforeopen(DataSet: TDataSet);



public
DLLDB : TDataBase ; //自己手工添加的变量
.
.
.
.
end;


procedure Test(TestDB: TdataBase);

implementation


{$R *.DFM}

procedure TForm1.Query1BeforeOpen(DataSet: TDataSet);
begin
(dataSet as TDBdatset).database:= DLLDB;
end;

procedure Test(TestDB: TdataBase);
begin
testform := Tform1.create(application);
testform.Dlldb := TestDB;
end;


记住一条: Object pascal 中 , Class 实际是一种指针
类型, 用过 C++Builder的人,都会发现, Vcl的对象
的属性都使用"=>"作分隔符,而不使用"."。这是指针构造
类型的典型用法。

不必在主程序和DLL中分别建立相同的TDatabase的实例,
那要重新连接, 太麻烦!!! (想一想TDataBase是
一个指针参数, 你就会明白了!)

一些建议:
1. 将一些不常用的功能放入某一个Dll, 在程序中使用
动态引入方式(也称显示加载〕, 这样可以减少内存的占用。

2. 尽量少分些Dll, 因为把form编译成dll, 要花大约100K的
长度放Form中用到的元件库, 如果把每个Form分别编译, 会
造成重复占用, 而实际上许多Form是重复使用元件的。建议
将多个Form编译成一个Dll, 这样能减少Dll的长度 。

3. 正确理解“空间换时间”。

如果不明白, 我向大家推荐一本书 :
徐新华:《Delphi 3 编程指南(上、下)》 RMB80.00(太贵);
上面专门有一章介绍动态链接库, 其中一些高级用法值得一读.


 
六兄的问题已经引起一个爆炸, 问题太大了, 我看你还是给各位加分后再分成几个
论题讨论吧

我还是坚持我的观点, 尽量使用通用form, 我就不信你那40~50个form不能精简。
作为一个软件搞了那么多花样, 你让用户怎么来掌握他呢? 即使不考虑用户方面也
得考虑你自己的使用说明书怎样写呀。

我的观点是一个好的软件除了满足功能需要外,最重要的是让用户使用起来更方便,
界面越简单、直观越好。

我曾经用Delphi给部队写过一个大的作战指挥系统,包括计划、报表、统计计算、
文书管理...。我相信其复杂程度绝对不比你的项目小, 结果只用了6个form, 其
中包括一个About, 一个系统设置, 一个用户管理, 其他主要工作都是在一个通用form下完成的。维护起来自然十分方便,追加数据库不用新建任何form和代码,
只需在系统设置中追加数据即可。
 
接受答案了.
 
最后总算搞定了。
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
965
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
顶部