在Delphi中如何维护COM+的状态信息[转载]

Star CCM+ 实战:旋风分离器网格加密策略与湍流模拟优化 本文针对Star CCM+中旋风分离器模拟精度不足的常见问题,深入剖析了网格质量的关键影响。文章重点介绍了通过局部网格加密策略,精准优化旋流核心区与入口区域的网格密度,从而在保证计算效率的前提下,显著提升湍流模拟的准确性与流场细节的捕捉能力,为工程实践提供了一套有效的优化方案。 阅读详情

刘晓明(cipherliu)

问题是这样开始的:我需要写一个COM+,用来连接不同的数据库。有的朋友可能会说,应该为每个数据库建立一个COM+,但是在我的系统里不能这样。我们在做一个教育辅助系统,用户是学校(当然包括学校里的老师、学生、家长),我们为每个学校建一个数据库,这些数据库的结构是相同。当然我们还有管理数据库,用于协调各数据库的关系。每增加一个学校用户,我们就激活一个新的数据库给客户使用,也就是说,我们的数据库的个数是不断增加的,而我们的客户端只有一个,我们不会为每个学校开发不同的客户端,我们的COM+也只有一组,而不是为每个数据库开发一组。所以我必须在COM+中根据用户的身份让它去连接不同的数据库。

很显然,这个COM+应当提供一个方法,让其调用者(可以是客户端应用程序,也可以是其它的中间件)去选择连接的数据库,在实际中我们是根据用户的ID在管理库中查到它的数据库名,然后连接用户数据库,在这里,为了简化问题,我们认为调用者已经知道了数据库的名字,而直接要求调用这个数据库。

在COM+的类中增加一个私有成员DBName:string,用于保存要连接的数据库名称。还应该提供这样一个方法来设置它的值,我开始是这样写的

procedure   TmtsDBConn.ConnectTo(sDBName:string);

begin

  try

     DBName:=sDBName;

     SetComplete;

  Except

    SetAbort;

  end;

end;

然后在其中放入ADOConnection,ADODataSet,和DataSetProvider控件,分别取名为adoc,adods,dsp。设置好它们之间的连接关系,把adoc的连接字符串设为连接数据库“DB1”,这是默认值,然后在adoc的BeforeConnect事件中:

adoc.ConnectionString:=ConnectStringA+'Initial Catalog='+DBName+';'+ConnectStringC;

这里的ConnectStringA和ConnectStringC是为了动态构建连接字符串,预先设置好的字符串常量,如下:

const

ConnectStringA='Provider=SQLOLEDB.1;Password=2003;Persist Security Info=True;User ID=sa;';

ConnectStringB='Initial Catalog=DB1;';

ConnectStringC='Data Source=server3;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=LXM;Use Encryption for Data=False;Tag with column collation when possible=False';

编译、安装这个COM+。然后编写客户端程序调用它。

在客户端程序中放一个DCOMConnection,连接到上面编写COM+服务器,再放一个ClientDataSet,设置它的RemoteServer和Provider属性,然后在它的CommandText中写入SQL语句。然后,放入DataSource控件和DBGrid控件,建立好它们之间的连接关系。最后放一个按钮,在它的Click事件中:

 

Dcomconnection1.Connected:=true;

Dcomconnection1.AppServer.connect('DB2');

ClientDataset1.Active:=true;

Dcomconnection1.Connected:=false;

 

这段代码是想测试一下,能不能访问到DB2数据库的数据。可是结果是,点下按钮时,总是报错,这是什么原因呢?

回到COM+的工程,调试它,在ConnectTo和adocBeforeConnect中设置断点,发现程序执行到

DBName:=sDBName;

时,确实已经把DBName的值设为”DB2”了,但是在执行

adoc.ConnectionString:=ConnectStringA+'Initial Catalog='+DBName+';'+ConnectStringC;

时,DBName又成了空字符串,所以出错了。

为什么DBName的值会丢掉呢?原来在是因为在ConnectTo中,调用了SetComplete方法,SetComplete方法认为这个COM+已经完成了任务,会释放这个COM+对象,所以连接数据库时,又创建了一个新的COM+,它的DBName当然是空值了。

找到了原因,把SetComplete改成EnableCommit; 编译,再运行客户端,终于运行成功,取回了DB2数据库中的数据。

可是在客户端程序中,放入另一个ClientDataSet,在打开ClientDataSet1之后,打开ClientDataSet2,想继续访问DB2中的数据,又报错了。把程序改成

 

Dcomconnection1.AppServer.connect('DB2');

ClientDataset1.Active:=true;

ClientDataset1.Active:=false;

ClientDataset1.Active:=true;

 

即使只使用一个ClientDataSet,在它关闭之后,再打开时,依然会出错。

但如果客户端写成

 

Dcomconnection1.AppServer.connect('DB2');

ClientDataset1.Active:=true;

Dcomconnection1.AppServer.connect('DB2');

ClientDataset2.Active:=true;

可以执行成功。但这样似乎很不好看,COM+为什么会在连接完数据库后又把自己释放呢?

原来,TmtsDataModule有一个AutoComplete属性,默认值是true,所以在连接完数据库之后,它还是会把自己释放。

把AutoComlete设成false后,还是出错,在COM+的OnActivate事件中跟踪发现,当它被激活时,AutoComplete属性被自动设为ture了,所以在它第一次连接数据库后,依然会把自己释放。

在COM+的OnOnActivate事件中,写上:

   AutoComplete:=false;

客户端一次连接,多次访问数据库也没有问题了。

但这样一来,COM+就不会自动释放了,需要在COM+中增加一个方法,在这个方法中SetComplete,然后在客户端用完COM+后,调用这个方法来释放COM+。

经过以上的摸索,得出以下的结论:在COM+中,如果要保持状态信息,需要做一些工作,因为COM+默认是无状态的,它每次被客户端调用后,都会判断是不是应该释放自己,如果我们不想它释放,就要人工加以干预,最后我们还要人工去释放它。

从噪声中提取真相:LabVIEW振动信号积分处理的降噪艺术 本文深入探讨了LabVIEW在振动信号积分处理中的降噪技术,揭示了如何通过选择性频率加权从噪声中提取关键故障特征。详细介绍了时域和频域积分方法的实现原理及优化策略,并结合工业案例展示了多轴信号联合降噪的实际应用效果,为设备状态监测提供了高效解决方案。 阅读详情

相关推荐

lp–mspm0g3507开发板进入低功耗模式怎么退出?烧程序烧着烧着就进来了,跳线帽没动过,且报错:Texas Instruments Debugger Error: DAP Co...如何解决?

🏆本文收录于 《全栈Bug调优(实战版)》 专栏,该专栏专注于分享我在真实项目开发中遇到的各类疑难Bug及其深层成因,并系统提供高效、可复现的解决思路和实操方案。无论你是刚入行的新手开发者,还是拥有多年项目经验的资深工程师,本专栏都将为你提供一条系统化、高质量的问题排查与优化路径,助力你加速成长,攻克技术壁垒,迈向技术价值最大化与职业发展的更高峰🚀!

**My Coding Family** 1534

Delphi创建COM+ 应用服务器(二)

<!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--><script type="text/javascript"

zgqtxwd的专栏 638

【YOLO11改进 - 特征融合】利用Hyper-YOLO 的混合聚合网络(MANet)改进yolo11,提升基础网络的特征提取能力

【YOLO11改进 - 特征融合】利用Hyper-YOLO 的混合聚合网络(MANet)改进yolo11,提升基础网络的特征提取能力

专注于图像领域,主要研究内容包括计算机视觉和深度学习,特别是在图像分类、目标检测和图像生成等方面有深入的研究和实践经验。 887

用VB实现COM+组件配置

用VB实现COM+组件配置http://www.ccw.com.cn/htm/app/aprog/01_5_11_2.asp 用VB实现COM+组件配置肖志云 01-5-11 上午 10:50:59 在Windwos2000的管理工具里有一个“组件服务”工具,可以实现对COM+组件的应用的安装、启动、删除和对组件的安装、删除。这在安装一个有COM+组...

weixin_30300523的博客 269

Delphi面向对象 COM [转载]Delphi面向对象学习随笔七:COM

2008-09-03 12:11Delphi面向对象学习随笔七:COM作者:巴哈姆特http://www.cnpack.org(转载请注明出处并保持完整) 上一篇,我们介绍了接口。如果没有接触过COM对象的话,你会觉得接口真的很麻烦,也许会有:“还不如直接定义一个类更方便”的想法。     的确,没有经过COM封装的接口确实比较麻烦。在我看来,没有经过COM封装的接口似乎没

delphicui的专栏 534

Delphi面向对象学习随笔七:COM(转)

====================================================== 注:本文源代码点此下载 ====================================================== delphi面向对象学习随笔七:com 作者:巴哈姆特 http://www.cnpack.org (转载请注明出处并保持完整) 上一篇,

javazhuanzai的专栏 364

Delphi之通过ADOX操作access数据库

[学习笔记]Delphi之通过ADOX操作access数据库作者:webfly 日期:2005-04-06字体大小: 小 中 大 作者:扬帆   网站: Email:888fly@163.com   如转载请保留此版权信息   Delphi7支持ADO(Microsoft ActiveX Data Objects)的支持,使得Delphi程序员可以彻底摆脱BDE,缩小

yanleigis的专栏 2458

Delphi深入DLL编程(2) (转载)

DLL比较复杂时,可以为它的声明专门创建一个引入单元,这会使该DLL变得更加容易维护和查看。引入单元的格式如下:   unit MyDllImport; {Import unit for MyDll.dll }   interface   procedure MyDllProc; … implementation    procedure MyDllProc;external...

a7129691的博客 344

delphi控件的笔记

首先要弄明白你要写的OCX是用在客户端还是用在服务器端假如用在客户端:1、创建打开delphi 7,选择菜单“new”->“other”->“activex”->“active form”->输入项目名称,系统自动给你创建了3个文件,一个是项目文件,一个是form的单元文件,还有一个后缀带TLB的文件。这三个文件中的你只需要更改form的单元文件,项目文件一般不需要写什么,...

weixin_30594001的博客 108

delphi有关

delphi有关 最近要用delphi做项目了,虽说delphi也玩了有不短的时间了,并且自认为有一定的‘造诣’:) 但是做实际的数据库应用却还真是第一次[em]e19[/em]。而且实际做起来才发现,自己对delphi的了解其实并没有自己想象的那么多。 主要是以前没有什么东西做呢,对delphi的研究方向也就比较流于理论、低层。比如他...

weixin_34336526的博客 110

Delphi面向对象学习随笔八:物理封装

Delphi面向对象学习随笔八:物理封装作者:巴哈姆特http://www.cnpack.org(转载请注明出去并保持完整) 前面说过的封装其实是逻辑意义上的封装。逻辑封装是对某一特定逻辑功能模块的封装,这个特定逻辑功能块可以是一个类,当然也可以是一个包,他们都有自己的逻辑边界。另一种封装方式,我们通常叫它为物理封装:物理封装其实是具体实现代码的物理集合,他可以以bpl,dll,com+等形式

intelsong的专栏 519

Delphi 的接口机制浅探

 Delphi 的接口机制浅探Delphi 的 Open Tools API 全是用 interface 实现的。为了学习 Open Tools API,只好先学 interface;为了学习 interface,又必须先学 COM。这样,我先花了三天看完了 COM 原理,再花二天考查 Delphi 的 interface 实现过程,得以整理出此文。这不是一篇关于接口应用的文章,而是接口操作的

yxj911的专栏 831

Delphi面向对象学习随笔八:物理封装(转)

Delphi面向对象学习随笔八:物理封装 作者:巴哈姆特 http://www.cnpack.org (转载请注明出去并保持完整) 前面说过的封装其实是逻辑意义上的封装。逻辑封装是对某一特定逻辑功能模块的封装,这个特定逻辑功能块可以是一个类,当然也可以是一个包,他们都有自己的逻辑边界。另一种封装方式,我们通常叫它为物理封装:物理封装其实是具体实现代码的物理集合,他可以以bpl,dll,...

weixin_30265171的博客 114

DELPHI中BDE、ODBC的配置注意

ODBC:在SQL EXPLORER中可以直接调用ODBC控制器,在ODBC的系统资料中增加的ODBC数据源,在重启SQL EXPLORER后才能出现在其中;BDE:在设置与ACCESS连接时,BDE存在本身的问题,至今未能成功的连接过,在BDE中可以创建与ODBC或者直接与数据库连接的别名

风之力的专栏 1978

封装的类型:类级别的封装和单元级别的封装

封装的类型:类级别的封装和单元级别的封装;1 类级别的封装:1.1 在类级别的封装中,对外的接口是public,publishd成员的集合,      protected,private的集合则属于列的实现细节;1.2 而对于该类的派生类来说,接口是public,published,protected的集合,      private部分为内部实现细节。2 单元级别的封装:2.1 在一个Unit中

风之力的专栏 1278

全局变量的使用注意

全局变量可以在var子句中直接初始化为一个值。记住,所有的全局数据会自动初始化为0,因此不要将全局变量初始化为一个"空"值比如 0、nil、、Unassigned、等等。这样做的一个理由是因为零-初始化的全局数据在exe文件中不会占据任何空间。而"空"值-初始化数据被存储在一个虚拟的数据段,它在应用程序启动后被分配在一段内存中。非零-初始化的全局数据在硬盘的exe文件占用空间。

风之力的专栏 1210

用DOA运行存储过程(转)

用DOA运行存储过程(转)用Delphi开发C/S结构的Oracle数据库软件时,为提高效率,通常将大批量的数据处理交给后台存储过程来完成。由于Delphi需通过BDE才能操作和处理各种数据库文件,这样不仅效率低,而且存在一定局限性,所以考虑采用第三方工具DOA来提高交互效率,方便前后台信息的传递。 DOA(即Direct Oracle Access的缩写)是荷兰Allround Auto

风之力的专栏 1052

DELPHI所有类的共性

有四个基本性的方法确保所有的类都表现出基本的行为。第一种行为是,所有的类都有默认的构造函数,可以创建实例。第二种行为是,所有的类都有析构函数,可以删除创建的实例。第三种基本的行为是,所有的类都可以调用继承而来的Free 方法而从内存中释放,Free 方法将检测对Nil 对象的调用以避免错误。第四种基本行为是,所有的类都可以响应Windows 消息。

风之力的专栏 960

华为数据治理之旅(2020年).pdf

华为数据治理之旅(2020年).pdf

176个HFSS仿真实例模型文件下载.zip

176个HFSS仿真实例模型文件下载.zip

上一篇: ADO.NET连接池
下一篇: 在Delphi7中调试COM+(转)
andyxujie
博客等级 码龄23年 0粉丝 63原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值