将 WCF 事务传递给 COM+






4.89/5 (2投票s)
本文提供了一个程序,演示了如何将 WCF 事务传递到 COM+。
引言
许多业务逻辑运行在 COM+ 类中。将这些逻辑公开为 WCF 服务日益成为一种需求。当 WCF 服务配置为 Web 服务时,任何客户端都可以访问它们。WCF 服务可以运行在事务中。当 WCF 服务调用 COM+ 方法时,该方法应该在 WCF 服务运行的同一事务中运行。本程序展示了如何实现这一点,因为关于此主题的文档很少。
背景
COM+
NET 中的 COM+ 功能可在 System.EnterpriseServices
命名空间下使用。任何继承 ServicedComponent
类的类都在 COM+ 中运行。如果此外,该类还定义了 Transaction(TransactionOption.Required)
属性,则该类的所有方法都将在事务中运行。
WCF
NET 中的 WCF 功能可在 System.ServiceModel
命名空间下使用。WCF 服务由 ServiceHost
类实现。该类在构造函数中接收实现服务方法的类作为参数。具有 OperationBehavior(TransactionScopeRequired:=True)
属性的方法将在事务中运行。
从 WCF 调用 COM+
WCF 服务可以实例化一个 COM+ 类并调用该类的一个方法。但是,COM+ 方法将在新事务中运行。为了使 COM+ 方法在同一事务中运行,事务范围的 InteropOption
必须设置为 Full
。
Using s As New TransactionScope(Transaction.Current, _
New TimeSpan(0, 1, 0), EnterpriseServicesInteropOption.Full)
'Call COM+
End Using
Using the Code
此程序是 Microsoft MSDN/Windows Communication Foundation Samples/Basic/Services/Transaction 的 Service Transaction Behavior 示例的一个修改版本。区别在于数据访问层驻留在额外的 COM+ 类中,而不是服务中。该解决方案包含四个项目
Dim client As New Tests.PX.CalculatorClient()
Using tx As New TransactionScope()
client.Add(100)
...
tx.Complete()
End Using
client.Close()
Tests.BE
:包含业务实体,在本例中仅包含类型化数据集LogData
。生成后事件会将程序集注册到 GAC。Tests.DA
:数据访问层,提供从数据库检索和更新记录的方法。生成后事件会将程序集注册到 GAC 和 COM+,并将config文件复制到相应的 GAC 文件夹。连接字符串定义在app.config文件中。程序集包含以下类ClassBase
:在 COM+ 中运行的类,提供从数据库读取数据和执行 SQL 语句的功能。ClassU
:在 COM+ 中运行的类,使用或创建事务,并提供一个函数,用dataset
中记录的更改更新表。
Tests.WS
:实现了 WCF 服务,并包含以下类<OperationContract()><TransactionFlow_ (TransactionFlowOption.Mandatory)>Function Add(ByVal n As Double) As Double
<OperationBehavior(TransactionScopeRequired:=True, TransactionAutoComplete:=True)> _ Public Function Add(ByVal n As Double) As Double Implements ICalculator.Add Using s As New TransactionScope(Transaction.Current, _ New TimeSpan(0, 1, 0), EnterpriseServicesInteropOption.Full) RecordToLog([String].Format(CultureInfo.CurrentCulture, _ "Adding {0} to {1}", n, runningTotal)) runningTotal = runningTotal + n s.Complete() End Using Return runningTotal End Function
host = New ServiceHost(GetType(CalculatorService))
ICalculator
:定义服务方法的接口。示例CalculatorService
:服务方法的实现。每个方法执行一个计算器操作,并将一条记录写入数据库的Log
表。示例- Program:包含启动服务的代码
Tests.UI
:包含一个用于测试服务的 Windows 窗体。该窗体提供“Test WS”按钮,该按钮会启动一个 WCF 事务,按顺序调用服务的四个方法,如果成功,则将事务标记为已完成。
要运行程序,请执行以下步骤
Throw New Exception("Ex1")
- 使用 Visual Studio 2010,打开解决方案Tests.WCFTrans.sln。
- 在app.config中设置连接字符串。它必须是有效连接字符串,指向您有权创建表的数据库。
- 生成解决方案。如果失败,请检查生成后事件中 gacutil 和 regsvcs 的路径是否正确。
- 您可以在组件服务 (Start/Run/comexp.msc) 中查看 COM+ 应用程序
Tests.DA
是否已创建。 - 通过双击Tests.WS\bin\Tests.WS.exe启动 WCF 服务。这将打开一个命令窗口,如下所示
- 在调试器中或使用可执行文件Tests.UI\Debug\bin\Tests.UI.exe启动
Tests.UI
。将出现以下窗体 - 选择菜单项**文件/重新创建**表。这将会在数据库上创建
Log
和Log_Audit
表。 - 按“Test WS”按钮。这将启动一个事务,调用服务的四个方法,然后完成事务。如果成功,将显示以下内容
- 要检查数据是否已写入数据库,请在数据库上执行命令:
SELECT * FROM Log
。 - 通过按前面提到的命令窗口中的**Enter**键停止服务。
- 要检查在服务中发生错误时是否未保存任何数据,请在
CalculatorService
类的Divide
方法中,在s.Complete()
语句之前添加以下代码 - 重新编译
Tests.WS
,并按原样启动它。 - 在
Tests.UI
的窗体中,再次单击“Test WS”按钮。将出现一条错误消息。 - 使用与以前相同的 SQL 命令检查数据库中是否没有写入任何数据。原因是,尽管服务方法
Add
、Delete
和Multiply
已成功完成并写入数据库,但服务方法Divide
失败。事务被中止,数据库中的更改被回滚。 - 您可以在 COM+ 和 UI 中引发异常,数据也会被回滚。
历史
- WCF 服务
CalculatorService
使用 COM+。UI 启动事务并调用服务。