配置事务
事务属性是一个声明性属性,可自动管理组件开发人员的事务。 通过设置此属性,无需在组件中使用显式事务控件。
COM+ 使用组件的事务属性来确定激活的每个对象所需的事务保护类型。 根据其要求,对象可以共享其调用方事务、需要新事务或在不使用事务保护的情况下操作。
COM+ 提供以下事务属性值:
-
已禁用
-
通常,仅当确定组件永远不会访问资源管理器时,才应设置此属性值。 禁用事务属性时,COM+ 会忽略组件在确定对象的上下文位置时的事务要求。 因此,对象可以共享其调用方上下文(和事务)。 将 COM 组件迁移到 COM+ 时,必须禁用事务属性,以保持与未配置 COM 组件相同的事务行为。
注意
未配置组件是 COM+ 应用程序中尚未安装的 COM 组件。
-
不支持
-
设置此属性值时,COM+ 可确保从组件创建的任何对象都不会参与事务,而不考虑其调用方的事务状态。 通过声明此值,可以确保对象不会在其调用方事务中投票,也不能开始其自身的事务。 “不支持”是所有组件的默认值。
-
支持
-
设置此属性值时,COM+ 可确保从组件创建的任何对象都参与事务(如果存在)。 如果希望对象在其调用方事务中共享,而无需其自己的事务,则声明此值。
-
必须
-
设置此属性值时,COM+ 可确保从组件创建的任何对象都是事务对象。 当 COM+ 使用“必需”设置激活对象时,它会查看其调用方的事务状态。 如果调用方具有事务,则新对象将包含在当前事务中。 否则,COM+ 将开始一个事务,使新对象成为事务的根。 这是执行资源活动的组件的首选设置,因为它有助于为这些活动提供事务保护。
-
Requires New
-
设置此属性值时,COM+ 可确保从组件创建的任何对象都必须作为事务的根参与新事务,而不考虑调用方的事务状态。 COM+ 自动启动与调用方事务不同的新事务。
注意
COM+ 不支持嵌套事务。 当一个事务对象调用标记为“要求新建”的另一个组件时,COM+ 将为新激活的对象创建独立的事务边界。 除非第一个事务显式记录第二个事务的结果,并根据这些结果修改其投票,否则第二个事务不会影响第一个事务。
事务属性依赖项
下表显示了每个 COM+ 事务属性值的特征,包括该值对事务特征的影响。 COM+ 对所有事务组件强制实施 JIT 激活和同步。
属性值 | 新事务 | 客户端事务 | 事务根 | JIT 激活 | 同步 |
---|---|---|---|---|---|
已禁用 |
从不 |
可能 |
从不 |
可选 |
可选 |
不支持 |
从不 |
从不 |
从不 |
可选 |
可选 |
支持 |
从不 |
如果客户端具有事务 |
从不 |
必须 |
必需 |
必须 |
可能 |
如果客户端具有事务 |
如果客户端没有事务 |
必须 |
必须 |
Requires New |
始终 |
从不 |
始终 |
必须 |
必须 |
事务边界
事务有一个开头、一个结尾,并且恰好发生一次。 在执行期间,事务可以调用资源(如数据库或队列),以完成一个或多个任务。 每个资源都位于事务边界内。 事务边界中的所有资源(可以跨多个进程和计算机边界)共享单个事务。 管理这些进程和计算机边界之间的一致性非常重要。
COM+ 根据为每个组件设置的事务属性的值自动管理事务边界来确保一致性。 COM+ 事务会自动流向指示参与事务的对象,并绕过指示在事务外部执行的对象。 COM+ 不支持嵌套事务。 相反,COM+ 事务不同且生存期较短。
事务边界中的第一个对象是事务的特殊对象,称为事务的根对象。 事务中只能有一个根对象。 根对象下的事务层次结构中的所有其他对象称为内部对象。
映射事务
确保对象在正确的事务边界内的一种方法是在开始编写组件之前映射事务。 通过映射事务,可以确定编写的每个组件的最佳设置。 对组件的使用方式的确定性越多,选择正确的事务属性值就越容易。
在运行时,COM+ 会查看事务属性,以确定对象是应是新事务的根、在现有事务中创建还是创建为非事务对象。
下图显示了可能的事务映射。 在此图中,客户端创建需要事务的对象 1。 由于不存在事务,COM+ 将创建事务 1 并在其中放置对象 1 作为根对象。 对象 1 创建对象 2,后者支持事务,因此放置在事务 1 中。 对象 2 创建对象 3,后者不支持事务,因此放置在所有事务之外。 对象 2 还会创建对象 4,后者需要事务,因此放置在事务 1 中。 对象 3 创建支持事务的对象 5。 但是,由于对象 5 是由事务中不存在的对象创建的,因此也将其放置在所有事务之外。 对象 4 将创建对象 6,后者需要一个新事务,因此 COM+ 会创建事务 2 并将对象 6 放置在其中作为根对象。 对象 6 创建对象 7,后者支持事务,因此放置在事务 2 中。
上图显示了两个潜在的问题区域。 首先,大部分工作在两个不同的事务之间拆分。 如果事务 1 在对象 4 创建对象 6 后失败,则事务 2 不受事务 1 的结果影响。 如果意外出现此结果,可能首选是将这两个事务的操作折叠成单个事务,通过将对象 6 的事务属性更改为“必需”可实现这一点。
映射图还显示,对象 3 和对象 5 是非事务对象,完全在事务 1 和 2 的范围外运行。 如果对象 5 更新持久数据,则可能需要重新考虑其非事务状态。 通过将对象 5 的事务属性更改为“必需”,可以将对象 5 放置在事务中。