相关名词:
(1) idispatch是COM object的接口, 在Delphi中通常指一个OleObject.
(2) OleVariant是一种COM object兼容的Variant类型, 可以通用任何Ole Automation 类型, 他与CreateOleObject创建的idispatch兼容
1:Com+的编写:
1:File---->New---->Other....---->ActiveX Library 标签 下的 Transactional Object
2: 然后填写: CoClss Name :类的名字,比如:ComPlus Threading Modal :线程模式:Apartment 选项: Supports transactions
3:然后在View--->Library的对话框中增加方法 注意:如果参数为输出的话,则类型要是指针型,比如:Long * ,然后修改后面的参数in :out,ret
4:最后完善增加的方法就ok了
2:客户端调用的编写:
1:先倒入Com+的接口类型. Project --->import Type Library---->选中你编写的Com+的类型,然后选择:Create Unit
3、安装COM+组件有两种方式,
第一种(推荐):如果是在IDE环境里,点击“Run->Install COM+ Objects”即可把打开的Active Library项目安装到COM+环境中,注意:如果打开的项目是 一个普通的Application项目,是不能被安装到COM+环境中的。 将要安装的com+打上勾,然后在application中有两个选项:install to existing application :表示你的com+安装在com服务器的哪个组件包中, install to New application:表示将当前com+组件安装到一个新的组件包中.
第二种办法:打开控制面板-> 管理工具->组件服务->计算机->我的电脑->COM+应用程序,在COM+应用程序的树项上点击 鼠标右键,选择“新建->应用程序”->创建一个空的应用程序,并为此应用程序命名,接下 来点击“下一步”直到结束即可。建立了空的COM+应用程序后,接下来就是把COM DLL安装 到COM+应用程序中了。在刚建立的空应用程序的树项中新建一个组件,选择“安装新组件”, 在打开文件对话框中选择要安装到COM+环境中的DLL文件,之后跟着向导做都可以了,要把 多个COM DLL安装到同一个COM+应用程序包中,只需重复以上步骤即可。
4、“导出客户端组件包”指的是把已经注册的组件导出为.msi格式的文件,这些文件在客 户端安装后,只会在客户端注册组件,而不会安装多余的文件。如果不在客户端注册组件, 是不不能调用位于服务器上的组件的(此指服务器和客户端分布在不同的机器上时)。
5:调试Com+程序 ---ok
1.打开Windows中的组件管理,找到要调试的组件包,点右键,选择属性,在高级这页里选择调试选项,打勾; 然后在下面的调试路径中找到/processID:{xxxxxxxxxxxxxxxxxxxxxxxxxxxxx} 复制出来
2.在dephi中Run | Parameters… HOST APPLICATION 填入 {系统路径}\system32\dllhost.exe PARAMETERS 粘巾 /processID:{xxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
3。很关键的一点:组件程序:project|option|linker|Include TD32 debug info 和Include remote debug symbols打勾
4.启动delphi,运行要调试的Com+程序,设置断点,然后运行客户端程序即可进入到Com+断点.
5.调试完后记得要在 Windows中的组件管理中的高级这页里调试选项勾去掉哟.
6:Com+需要注意的地方:
1:客户机运行就会报 interface not supported 错误 大致原因:轻舞肥羊 (2004-05-09 11:00:01) COM+的权限依赖于Windows的权限配置,在服务器需要有客户机的用户名和密码。 如果还不行,就在服务器上重新安装com+,重新导出.
2:建立工程时,com+不能包含在工程组中.(我的实践)
3:COM+不支持Oracle吗?在用事务的时候出错:Using Oracle with Microsoft Transaction Server and COM+
7:在Com+中添加远程数据模块
1:File---->New---->Other....---->Multitier 标签 下的 Transactional Data Module
2:然后在View--->Library的对话框中增加方法.
8:Com+中传递数组
先定义数组: type TDataRecord = record A: Byte; B: LongWord; C: Word; D: LongWord; end; 1:server: function GetData: OleVariant; var P: Pointer; begin VarClear(Result);//不知D5有没。 try Result := VarArrayCreate([0, SizeOf(TDataType)], varByte); P := VarArrayLock(Result); //Data: TDataType为你要传的记录类型 Move(Data, P^, SizeOf(TDataType)); finally VarArrayUnLock(Result); end; end; 2:Client procedure GetFile(const FileName: string); var P: Pointer; V: OleVariant; Data: TDataType; begin FillChar(Data, SizeOf(Data), 0); V := SocketConnection1.AppServer.GetData; try P := VarArrayLock(V); Move(P^, Data, SizeOf(Data)); finally VarArrayUnLock(V); end; end; 9:Com+中传递记录集 下面xeen 实验成功 uses ADOInt******************************************************************************************* 可以;你可以将ADO的数据作为一个Variant类型的变量进行传送:adodataset1.RecordSet这是原生的ado数据 这是服务端的一个方法的代码:把CodeSet的类型改为Variant*[in,out] function TADORec.getData: OleVariant; begin AdoDataSet1.Open; result := adodataset1.RecordSet; end; ************************************************************************************************************************ 客户端 uses adoint; var MyRecordset :_recordset; begin MyRecordset := IUnknown(CodeSet) as _recordset ************************************************************************************************************************** Com基本概念:
1:COM是一个基于二进制的标准。打个比方,我们用Delphi实现了一个对象,一般情况下,我们只能在Delphi来生成这个对象的实例并调用,而如果我们用Delphi实现了一个COM对象的话,我们可以用VC、VB或者其他任何一种支持COM对象的语言来生成实例和调用。反过来也一样,我们可以在Delphi中使用各种COM对象,而不用介意它是用什么语言编写的。COM提供了分布式COM对象的机制,形象地说你可以调用另一台机器中的COM对象。COM+则是MTS的一个升级,在COM的基础上进一步提供了事务处理和其他很多Pool技术。
2:线程模式:Apartment:多个线程服务.
3:当建立Com+时选择的事务模式为Requires a Transaction,Com+会根据客户的的请求建立相应的事务,不仅仅时数据库,还会有系统资源等事务.成功SetComplete.回滚SetAbort. 选择Requires a Transaction表示当用户调用这个COM+组件时,COM+环境会为这个组件建立一个新的事务上下文,这和数据库的事务不是一回事。当你的COM+组件提交数据时如果出错,应该告诉事务上下文,只要调用COM+组件的SetAbort方法就可以。这样一来,处于同一个事务上下文的所有COM+组件都会Rollback。如果数据提交成功,应该调用SetComplete,不调用这个方法也可以,因为在默认情况下,COM+组件的事务状态设置为EnableCommite。当处于同一事务上下文的所有COM+组件对象都调用了SetComplete时,该事务上下文才会真正的向数据库提交数据。
4:SetAbort合SetComplete是否正确调用
5:(阿朱) 建议:多个DLL在一个包,一个DLL中的COM公用一个ADOCONNECTION 6:问题:我已经在Transactional Data Module的Pooled属性里面设置了True了,但是在Win2000的组件服务管理的“组件属性”的“激活”一栏里面,仍然无法打开“启用对象共用”的选项 --->您可以将线程模式设置为tmNeutral或者tmBoth都可以。
Com有需要研究和有疑问的地方:
1:Com+的模式:
2:到Com+的资源Pooling机制
3:用delphi6 开发Com+,用Neutral模式,尽量用Object Pooling,当然就是要无状态了,事务要尽量短,避免死锁,用ADO不要用BDe.Dbexpress等.
4:我的做法是,按功能划分组件,把查询和更新分为两个功能组件,因为查询不需要事务,所以只要支持事务就行了。更新一般需要事务
5:COM+的事务属性 COM+的事务默认级别是序列 Read,而不是我们认为的commit Read,而且我们设置AdoConnection的隔离级是不 管用的,只能强制用显式的SQL才能起效果。 例如: 一个中间层COM select * from a where py_code like 'S%' 继续下面有很多代码 另一个中间层COM update a set py_code=py_code where py_code like 'B%' 这时这个COM将会死锁等待,虽然改动的不是一个数据也会死锁 用Commit Read 或UnCommit Read不会 建议: 所以被多个子系统更新或读的表,要在最后打开和更新,不要早。另外可以强制改变ADOCONNECTION的隔离级
6:Com+中如何进行事务处理??? 在COM+中,如何使用SetComplete和SetAbort进行事务管理?? 老兄,SetComplete和SetAbort怎么能在客户端调用呢?这样肯定是不行的。要保证事务,就在服务器端声明一个专门保存的接口方法,例如: procedure UpdateMyData(var AData1, AData2: OleVariant; var AMaxError, AErrorCount: Integer); begin try DataSetProvider1.Data := AData1; DataSetProvider1.ApplyUpdate(AMaxError, AErrorCount); DataSetProvider2.Data := AData2; DataSetProvider2.ApplyUpdate(AMaxError, AErrorCount); SetComplete; except SetAbort; end; end;
7:,在组件管理器中的“事务列表”里也看不到事务(应该有事务的时候),怎么看?
8:Com+的两大研究:事务 和 pooling
9:做一个提交用的COM+对象和一个协调用的COM+对象 ???