📄 208003.htm
字号:
If Error Then 呼叫ObjectContext.SetAbortElse 呼叫ObjectContext.SetComplete</span><span id=Layer53></pre></font></div><p><font size=2 color=#3c3c3c face=arial>或许发行两个查询的method使用了</span><span id=Layer54> <a target='_new' href=206.htm#>第六章</span><span id=Layer55></a> 描述的ADO物件,然後呼叫GetObjectContext以获得它的IObjectContext介面。若在查询执行的过程中发生问题,则MoveMoney呼叫SetAbort method,若没有发生任何问题,便呼叫SetComplete。</span><span id=Layer56></font></p><p><font size=2 color=#3c3c3c face=arial>注意交易性的COM物件并不会使用任一个ADO method来控制</span><span id=Layer57> <a target='_new' href=206.htm#>第六章</span><span id=Layer58></a> 中所描述的交易。同样也没有简单的方式来设定交易执行时的隔离等级(isolation level)。取代的做法,由COM runtime初始的交易永远以Serializable isolation level进行,也就是</span><span id=Layer59> <a target='_new' href=206.htm#>第六章</span><span id=Layer60></a> 所描述的最严格的选项。</span><span id=Layer61></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b> 附注</b></font><p><font size=2 color=#3c3c3c face=arial>注意交易性的COM物件并不会使用任一个ADO method来控制</span><span id=Layer62> <a target='_new' href=206.htm#>第六章</span><span id=Layer63></a> 中所描述的交易。同样也没有简单的方式来设定交易执行时的隔离等级(isolation level)。取代的做法,由COM runtime初始的交易永远以Serializable isolation level进行,也就是</span><span id=Layer64> <a target='_new' href=206.htm#>第六章</span><span id=Layer65></a> 所描述的最严格的选项。</span><span id=Layer66></font></p><hr><p><font size=2 color=#3c3c3c face=arial>就如同这个例子带来的启发,对於那些属於COM+应用程式一部份的元件来说,元件中每个method结束时呼叫SetComplete或SetAbort是相当平常的。事实上,COM+也允许你设定一个属性以便让这些呼叫的其中一个自动地执行,称为Auto-done属性。已设定元件上的一个或多个method都可以设定这个属性。若Auto-done 的功能开启,实际上若这个method没有回传任何的错误(同时也没有明确地更改预设值),COM runtime将会自动地呼叫SetComplete。若method回传一个错误,则实际上Runtime会呼叫SetAbort。这个观点将可让程式设计师不需在每个method结束时撰写这些呼叫SetComplete或SetAbort等等一成不变的程式码。</span><span id=Layer67></font></p><p><font size=2 color=#3c3c3c face=arial>Auto-done 属性可让你省掉呼叫SetCom-plete 与Set-Abort的动作</span><span id=Layer68></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>Auto-done 属性可让你省掉呼叫SetCom-plete 与Set-Abort的动作</span><span id=Layer69></font></p><hr><font color=#3e72d7 face=arial size=4><b>设定元件组态以便使用自动交易处理</span><span id=Layer70></b></font><p><font size=2 color=#3c3c3c face=arial>其实到目前为止有一个令人瞠目结舌的漏洞∶元件要如何组态才能允许COM runtime得知当一个新method call到达时,是否要开始一个交易?答案是已设定元件(configured component)拥有一个异动属性。通常这个属性都是在程式开发环境中设定的,如Visual Basic或Visual C++,或使用元件服务管理工具。无论如何设定的,属性的值将会和元件的资讯一同储存在RegDB中,当某个类别的实例(instance)建立时进行读取,以便成为新物件context资讯的一部份。</span><span id=Layer71></font></p><p><font size=2 color=#3c3c3c face=arial>COM runtime以元件的异动属性为基础来决定是否要开始一个新交易</span><span id=Layer72></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>COM runtime以元件的异动属性为基础来决定是否要开始一个新交易</span><span id=Layer73></font></p><hr><font size=3 color=#3e74d7 face=arial><b>COM+定义五种异动属性可能的值∶</span><span id=Layer74></b></font><font size=2 color=#3c3c3c face=arial><ul><font size=2 face=arial color=#3c3c3c><li><font size=2 face=arial color=#3e80d7><b> 需要新增</span><span id=Layer75> </b></font>(</span><span id=Layer76><font size=2 face=arial color=#3e80d7><b> Requires New</span><span id=Layer77> </b></font>) 当COM runtime接收到从一个异动属性为这个值的第一个method call呼叫时,会开始一个新交易。</span><span id=Layer78></li><br></font><font size=2 face=arial color=#3c3c3c><li><font size=2 face=arial color=#3e80d7><b> 必需的</span><span id=Layer79> </b></font>(</span><span id=Layer80><font size=2 face=arial color=#3e80d7><b> Required</span><span id=Layer81> </b></font>) 若从一个异动属性值为这个值的元件建立起物件的建立者本身不属於某个交易的一部份,COM runtime在接收到对此物件的第一个呼叫时便会开始一个新交易。若建立者已存在於某个交易中,在第一个呼叫到达时,COM runtime将不会开始一个新交易。取代的做法,这个method所进行的工作将会成为建立者交易的一部份。</span><span id=Layer82></li><br></font><font size=2 face=arial color=#3c3c3c><li><font size=2 face=arial color=#3e80d7><b> 支援</span><span id=Layer83> </b></font>(</span><span id=Layer84><font size=2 face=arial color=#3e80d7><b> Supported</span><span id=Layer85> </b></font>) 当COM runtime接收到建立一个异动属性为这个值的method call时,永远不会开始一个交易。若物件的建立者已是某个交易的一部份,这个method所进行的工作将会成为那个交易的一部份。若建立者并不属於一个交易,则这个method所进行的工作将不会在交易中执行。</span><span id=Layer86></li><br></font><font size=2 face=arial color=#3c3c3c><li><font size=2 face=arial color=#3e80d7><b> 不支援</span><span id=Layer87> </b></font>(</span><span id=Layer88><font size=2 face=arial color=#3e80d7><b> Not Supported</span><span id=Layer89> </b></font>) 就如同支援(Supported)一样,COM runtime接收到建立一个异动属性为这个值的method call时,永远不会开始一个交易。更进一步来说,即使物件的建立者已是某个交易的一部份,这个method进行的工作将会在这个交易之外执行。设为不支援的物件,无论如何其method是永远不会在交易之中执行的。这也是异动属性的预设值。</span><span id=Layer90></li><br></font><font size=2 face=arial color=#3c3c3c><li><font size=2 face=arial color=#3e80d7><b> 停用</span><span id=Layer91> </b></font>(</span><span id=Layer92><font size=2 face=arial color=#3e80d7><b> Disabled</span><span id=Layer93> </b></font>) 就如同不支援(Not Supported)一样,异动属性设定为停用的物件,其method执行时永远不会在COM+自动交易处理机制中执行。不过,与不支援不同点在於这个选项会告诉COM runtime,当判断它是否共享建立者物件的context时,忽略掉物件的异动属性值。</span><span id=Layer94></li><br></font></ul></font><p><font size=2 color=#3c3c3c face=arial>在</span><span id=Layer95> <a href=" #8-6" target=_new>图8-6</span><span id=Layer96></a> 到</span><span id=Layer97> <a href=" #8-8" target=_new>8-8</span><span id=Layer98></a> 中的范例所示,实作MoveMoney的物件必需将异动属性设定为需要新增(Requires New)或必需的(Required)。 当客户端呼叫这个method时,没有其它可能的选择会让COM runtime开始一个新交易。</span><span id=Layer99></font></p><p><font size=2 color=#3c3c3c face=arial>那麽若元件执行的某件工作绝对要成为交易的一部份时又该如何呢 ?很可能元件的异动属性被管理者设定成不支援。若应用程式在这种状况下执行, 那就要准备面对接踵而来的混乱。为了避免这个问题的发生,物件中的method可以呼叫IObjectContext::IsInTransaction。若它回传False,则代表发生一些错误,物件便可以采取适当的行对,如发出错误讯息,然後关闭行程。</span><span id=Layer100></font></p><p><font size=2 color=#3c3c3c face=arial>物件能检查是否执行在一个交易中</span><span id=Layer101></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>物件能检查是否执行在一个交易中</span><span id=Layer102></font></p><hr><font color=#3e72d7 face=arial size=4><b>多个物件的自动交易处理</span><span id=Layer103></b></font><p><font size=2 color=#3c3c3c face=arial>只牵涉到一个物件的COM+自动交易处理是很简单的。不过,在真实的应用程式中,经常将呼叫许多不同物件的method等动作包装在同一个单独的交易中。举例来说,应用程式可能包含一个COM元件,此元件知道如何将一份顾客订单的产品资料记录到资料库;而另一个COM元件则知道如何透过顾客的信用卡收取帐款。新增一个顾客的订单资讯,需要呼叫这两个物件的method,以确保所有的动作能够包装在一个交易之中进行。然後,重要的是需了解当多个物件以不同的方式进行组态时,自动交易处理会如何运作。</span><span id=Layer104></font></p><p><font size=2 color=#3c3c3c face=arial>一个交易之中可以包含多个物件一起运作</span><span id=Layer105></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>一个交易之中可以包含多个物件一起运作</span><span id=Layer106></font></p><hr><p><font size=2 color=#3c3c3c face=arial>第一个问题,便是察看包含多个物件的交易是如何结束的。前面的范例仅包括一个物件,因此当物件呼叫SetComplete或SetAbort时,交易便结束了。若交易之中包含了多个物件,情况就变得复杂些。为了要了解COM+是如何处理这种情况时,假想一个状况,如图8-9所示。在步骤一,客户端建立一个类别A的COM物件,物件中的程式码将异动属性设定为需要新增(Requires New)。在步骤二,客户端呼叫物件A的一个method。这个method call 将会被拦截,然後COM runtime根据物件的context中的异动属性值决定开始一个新交易。就如同前面的例子,runtime告诉DTC以便开始一个新交易,然後将这个呼叫传送到物件A真正实作method的所在。</span><span id=Layer107></font></p><br><center><a target=_new href=imagesh/8-9.gif><img border=0 src='imagesl/8-9.gif'></a></center></span><span id=Layer108><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b> 图8-9</span><span id=Layer109> </b></font>客户端对一个物件的第一个method call会让COM runtime通知DTC以开始一个新交易</span><span id=Layer110></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>接下来,假设物件A的method建立物件B,如图8-10步骤五所示。同样地,假设B的异动属性设定为必需的(Required)。B执行的工作将会成为COM runtime已启动的交易之一部份。当B建立後,有些资讯便从A的context复制到B的context,如交易的识别码。同样的动作会发生在步骤七,当A建立物件C,C的异动属性同样设定为必需的(Required)。C也会加入目前的交易中,A的context中某些资讯也会被复制到C的context中,如图步骤八所示。A、B、C这叁个物件形成一棵交易树,而A就是交易的根源。</span><span id=Layer111></font></p><p><font size=2 color=#3c3c3c face=arial>交易中的多个物件形成一棵交易树</span><span id=Layer112></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>交易中的多个物件形成一棵交易树</span><span id=Layer113></font></p><hr><br><center><a target=_new href=imagesh/8-10.gif><img border=0 src='imagesl/8-10.gif'></a></center></span><span id=Layer114><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b> 图8-10</span><span id=Layer115> </b></font>当一个物件建立另一个部件,交易资讯便从建立者的context复制到新物件的context中。</span><span id=Layer116></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>现在假想A呼叫物件B中的一个method,如图8-11步骤九。这个method进行一些工作,如更新资料库。然後,在步骤十,呼叫SetComplete。事实上B已完成它的工作,并同意确认这个交易且记录在B的context中,不过COM runtime此时并未结束这个交易。当多个物件加入同一个交易之中时,交易会在根物件呼叫SetComplete或SetAbort时结束。因此,在步骤十一,A呼叫物件C的method进行一些工作,然後在步骤十二,这个method同样呼叫SetComplete,不过交易仍未结束。</span><span id=Layer117></font></p><p><font size=2 color=#3c3c3c face=arial>根物件呼叫SetComplete或SetAbort导致交易的结束</span><span id=Layer118></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>根物件呼叫SetComplete或SetAbort导致交易的结束</span><span id=Layer119></font></p><hr><p><font size=2 color=#3c3c3c face=arial>这个交易将在图8-12步骤十叁,物件A呼叫SetComplete时结束。此时,COM runtime检查交易中牵涉到的所有物件的之context(A、B、C的Context),如步骤十四。若交易中所有的物件都呼叫SetComplete,如这个范例,则COM runtime将会告诉DTC确认这个交易,如步骤十五。不过如果任一个物件呼叫SetAbort,则runtime 将会指示DTC复原这个交易。交易不是全部成功就是全部失败(all-or-nothing)的事件,因此任何违反一致性的动作,都代表交易中所有物件对所有资源管理者进行的存取动作都将会复原。最後,在步骤十六,客户端发出的method call回传,而整个过程到此结束。</span><span id=Layer120></font></p><p><font size=2 color=#3c3c3c face=arial>若要决定确认或取消,COM runtime检视交易中每个物件的投票结果</span><span id=Layer121></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>若要决定确认或取消,COM runtime检视交易中每个物件的投票结果</span><span id=Layer122></font></p><hr><p><font size=2 color=#3c3c3c face=arial>更精确地说,当物件A的method呼叫SetComplete,将控制权转交给COM runtime时,交易将会结束。</span><span id=Layer123></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b> 附注</b></font><p><font size=2 color=#3c3c3c face=arial>更精确地说,当物件A的method呼叫SetComplete,将控制权转交给COM runtime时,交易将会结束。</span><span id=Layer124></font></p><hr><br><center><a target=_new href=imagesh/8-11.gif><img border=0 src='imagesl/8-11.gif'></a></center></span><span id=Layer125><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b> 图8-11</span><span id=Layer126> </b></font>交易树根源以下的所有物件都不会因为呼叫了SetComplete而结束交易</span><span id=Layer127></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>那麽当根物件呼叫SetComplete或SetAbort,而交易中根物件以下的某个物件未呼叫SetComplete或SetAbort时会发生何事?有点令人讶异,根物件下一层的物件将会被解译为呼叫SetComplete 预设为确认。不过假设一个物件加入一个交易中,不过在它还处於中间状态(intermediate state)时就必需回到它的呼叫者。它尚未呼叫SetComplete或SetAbort,不过它希望在进行一些动作後再进行呼叫。虽然此时它尚未准备要进行确认的动作,但此时根物件呼叫了SetComplete,这个物件预设将视为投票表示确认。为了避免这个情况,物件可以在控制权回到它的呼叫者之前呼叫IObjectContext::DisableCommit。若物件必需要呼叫SetAbort时,这麽做将可更改物件预设的确认行为。现在原本要确认的交易便会因此而导致取消,所有曾做过的事都将还原。当物件想再度进行确认的动作时,便可以呼叫IObjectContext::EnableCommit更改它预设的投票动作。当物件的工作完成,它将会呼叫SetComplete或SetAbort。</span><span id=Layer128></font></p><p><font size=2 color=#3c3c3c face=arial>物件可以更改预设的确认行为</span><span id=Layer129></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>物件可以更改预设的确认行为</span><span id=Layer130></font></p><hr><br><center><a target=_new href=imagesh/8-12.gif><img border=0 src='imagesl/8-12.gif'></a></center></span><span id=Layer131><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b> 图8-12</span><span id=Layer132> </b></font>当交易树的根物件呼叫SetComplete或SetAbort时,交易便结束了。</span><span id=Layer133></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>另一件有趣的事是:不同的异动属性设定将会如何交互影响。先前描述的范例是个相单简单的范例,叁个物件进行的工作组成的一个交易。图8-13显示另一种可能性。在此,一个客户端从一个元件中建立一个物件,元件的异动属性设定为必需的(Required)。这个物件接着建立另一个物件(同样设定为必需的)。客户端是一个在桌上型电脑上执行的软体,同时在这个范例中它目前并非是交易的一部份。因此这个客户端对物件A发出的第一个method call将会导致COM runtime开始一个新交易,这是因为A需要一个交易,而呼叫A的人并没有加入任何交易之中。当A建立,然後呼叫物件B,物件B也标示为必要的,COM runtime并没有开始一个新交易。就像A一样,B必需执行在一个交易之中,不过因为它的建立者已存在交易之中,所以B就加入既存的交易。物件A与B执行的工作都将成为同一个交易的一部份。就如同我们讨论的一样,当A,也就是根物件呼叫了SetComplete或SetAbort时,交易便结束了。</span><span id=Layer134></font></p><p><font size=2 color=#3c3c3c face=arial>标示为必需的(Required)的物件可以加入建立者的交易之中</span><span id=Layer135></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>标示为必需的(Required)的物件可以加入建立者的交易之中</span><span id=Layer136></font></p><hr><br><center><a target=_new href=imagesh/8-13.gif><img border=0 src='imagesl/8-13.gif'></a></center></span><span id=Layer137><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b> 图8-13</span><span id=Layer138> </b></font>物件A与B执行的工作都将成为同一个交易的一部份</span><span id=Layer139></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>图8-14 展示一个更复杂的情况。跟往常一样,一个客户端建立并呼叫物件A的method,物件A标示为必需的,使得COM runtime开始一个新交易。然後A建立并呼叫物件B,物件B在这个例子中标示为支援(Supported)。支援的意思是「我不在乎,我将会跟我的建立者做一样的事。」在这个情况下,因为B的建立者已是交易的一部份, B便很快乐的加入这个交易之中。不过当A接着建立并呼叫物件C时,物件C标示为需要新增时,事情就有了变化。C的异动属性设定通知COM runtime,C坚持要一个新交易,不管建立者的状况。这样的结果将会导致COM runtime开始一个另一个交易,其中包含物件C所做的事。当A呼叫SetComplete或SetAbort时,包含物件A与B的交易将会结束。而C的交易则在C呼叫SetComplete或SetAbort时结束。这两个交易一点关系都没有,因此一笔交易的结果并不会影响到另一笔交易。</span><span id=Layer140></font></p><p><font size=2 color=#3c3c3c face=arial>标示为需要新增的物件将不会加入建立者的交易中</span><span id=Layer141></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>标示为需要新增的物件将不会加入建立者的交易中</span><span id=Layer142></font></p><hr><p><font size=2 color=#3c3c3c face=arial>图8-15显示另一种可能性。在此物件A与B已如前面的例子的方式建立了。然而物件C标示为必需的(Required),它是由另一台Windows 2000伺服器机器建立的。这样的动作跟上个例子并没有什麽不同,物件C仍旧会加入A的交易之中,就如同它是由同样一台机器上的A建立的一样。不管物件是否存在於相同的行程中,或在同一台机器上的不同行程中与否,它们可以属於同一个交易。COM runtime与DTC将物件存在位置的细节隐藏起来。</span><span id=Layer143></font></p><p><font size=2 color=#3c3c3c face=arial>交易可包含执行在不同台机器上的物件</span><span id=Layer144></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>交易可包含执行在不同台机器上的物件</span><span id=Layer145></font></p><hr><p><font size=2 color=#3c3c3c face=arial>自动交易处理其中一个可能会令人讶异的地方,是有关牵涉到一个交易中的物件并不知道交易最後的结果。在牵涉到多个物件的交易情节下,根物件必须呼叫SetComplete,但因下层物件已呼叫了SetAbort,则整个交易将会取消。即使交易中只包含一个物件,也有可能发生物件发出的SetComplete要求并未让交易进行确认。这是很可能的,举例来说,加入一个交易中的某个DBMS必须在其二阶段交付的确认过程中,取消交易的进行导致整个交易进入复原的状态。</span><span id=Layer146></font></p><p><font size=2 color=#3c3c3c face=arial>交易中的物件并不知道交易最後的结果是确认或取消</span><span id=Layer147></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>交易中的物件并不知道交易最後的结果是确认或取消</span><span id=Layer148></font></p><hr><br><center><a target=_new href=imagesh/8-14.gif><img border=0 src='imagesl/8-14.gif'></a></center></span><span id=Layer149><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b> 图8-14</span><span id=Layer150> </b></font>因为C标示为需要新增,因此这个情节下会建立两个交易。</span><span id=Layer151></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>交易性COM元件的程式设计师应该努力建立元件完成它们的工作,不管结果如何,最後投票决定要∶SetComplete或SetAbort。理论上,这些元件不应该关心同一个交易中其它的元件在干什麽,或是否有其它的元件与自己处於相同的交易之中。在某些情况下,这并不实际。</span><span id=Layer152></font></p><p><font size=2 color=#3c3c3c face=arial>物件可以通知呼叫它的人,自己要取消交易的执行</span><span id=Layer153></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>物件可以通知呼叫它的人,自己要取消交易的执行</span><span id=Layer154></font></p><hr><p><font size=2 color=#3c3c3c face=arial>举例来说,若交易树下层元件决定欲呼叫SetAbort,无论如何,根物件都可能会避免进行一些需进行复原的耗时工作。若要实践这件事,下层的元件应该回传一个参数给呼叫者,或产生一个错误,以便指明欲取消交易,在继续执行之前先检查这个值,然後呼叫者便可以决定是否值得多做一些事情。</span><span id=Layer155></font></p><br><center><a target=_new href=imagesh/8-15.gif><img border=0 src='imagesl/8-15.gif'></a></center></span><span id=Layer156><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b> 图8-15</span><span id=Layer157> </b></font>在不同机器上的物件们可以隶属於同一个交易。</span><span id=Layer158></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>然而,要了解发出第一个呼叫的原始客户端,如ASP网页,总是知道发生的事情,因为客户端察看它所呼叫method的回传值。若一切顺利进行,这个回传值便会指明工作成功。不过若交易取消了,即使取消的原因是因为DBMS在二阶段交付的过程中决定的,COM runtime将会修改method的回传值,确保客户端能得知它的要求已失败。</span><span id=Layer159></font></p><p><font size=2 color=#3c3c3c face=arial>原始的客户端得知交易要确认或者是取消</span><span id=Layer160></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>原始的客户端得知交易要确认或者是取消</span><span id=Layer161></font></p><hr><p><font size=2 color=#3c3c3c face=arial>最後一件值的注意的事便是Transaction Context物件,它是COM+提供的一个标准元件。这个物件不会自动建立交易的边界,而是允许一个客户端明确地将许多物件包装在一个交易中。关於Transaction Context物件有两个重点需要了解:第一,不要把它和提供IObjectContext介面的object context搞混了。除了在名称上有点类似之外,这两个物件是完全不同的。第二,要了解你永远不需要使用这个物件。这个机制是建构在自动交易处理之上,因此你不会得到额外的功能。同样的, Transaction context object有许多限制,举例来说,它必需与它的客户端执行在同一个行程中。这对远端的客户端来说是个大问题。一般而言,程式设计师应直接依赖自动交易处理的机制,而不要使用Transaction context object。它很少会让你得到什麽好处。</span><span id=Layer162></font></p><p><font size=2 color=#3c3c3c face=arial>Transaction context Object允许一个客户端将许多物件组成一个交易</span><span id=Layer163></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>Transaction context Object允许一个客户端将许多物件组成一个交易</span><span id=Layer164></font></p><hr><font color=#3e72d7 face=arial size=4><b>交易逾时</span><span id=Layer165></b></font><p><font size=2 color=#3c3c3c face=arial>理想的情况,一个应用程式执行的每个交易都应该愈短愈好。因为每笔交易事件都会锁定某些资料,允许交易维持的时间超过一或两秒钟,将使得这些资料无法让其它的交易存取。这样会让应用程式变慢,因为其它的交易可能会等待一个耗时良久的交易执行完毕。一个好的应用程式设计师将尽其所能以确保没有任一个交易执行得时间太久。</span><span id=Layer166></font></p><p><font size=2 color=#3c3c3c face=arial>交易应该简短</span><span id=Layer167></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>交易应该简短</span><span id=Layer168></font></p><hr><p><font size=2 color=#3c3c3c face=arial>不过有一种情况使得交易不得不花很长的时间执行。假设物件X执行的一个交易需要同时存取特定顾客的存款帐户与支票帐户。假设另一个由物件Y开始的交易恰巧同时在执行之中,它也需同时存取这两个户头。现在假想一下物件X先存取存款帐户,并锁定此帐户,而物件Y存取了支票帐户并锁定此帐户。每个物件需要存取的帐户都被另一个元件锁定了,没有任一个物件的工作可以往下执行,直到取到欲存取的帐户为止。当然这样的结果就是所谓的死结(deadlock) 这两个交易都被困住了。</span><span id=Layer169></font></p><p><font size=2 color=#3c3c3c face=arial>交易可能会产生死结问题</span><span id=Layer170></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>交易可能会产生死结问题</span><span id=Layer171></font></p><hr><p><font size=2 color=#3c3c3c face=arial>若要解决这个问题,COM runtime实行了交易逾时。可透过元件服务管理工具进行设定,这个值可以控制交易在自动取消之前,持续执行的时间长度。预设值是60秒,不过你可以将之设定为0到3600之间的值。若将交易逾时设定为0就会将这个功能关闭,允许交易无期限执行。在除错时这将会相当的有用,不过在上线时间就不是个好主意了。因为死结的问题可能永远都不会被发现,而无限期执行。</span><span id=Layer172></font></p><p><font size=2 color=#3c3c3c face=arial>若交易逾时,COM runtime将会取消交易</span><span id=Layer173></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>若交易逾时,COM runtime将会取消交易</span><span id=Layer174></font></p><hr><p><font size=2 color=#3c3c3c face=arial>交易逾时的存在对COM+应用程式的设计具有深厚的影响力。要知道为什麽吗?想像一个使用了交易的物件,但物件的每个method并不一定是呼叫SetComplete或SetAbort做为结束。在这个情形下,当客户端第一次呼叫了此物件的method,交易就开始了,不过直到客户端呼叫到物件的某个以SetComplete method或SetAbort method 结尾的method之前,交易并不会结束。</span><span id=Layer175></font></p><p><font size=2 color=#3c3c3c face=arial>这是很罕见的情况,不过或客户端呼叫交易树根物件的IUnknown::Release,也同样会结束一个交易。预设COM runtime将这个状况视为根物件已呼叫SetComplete,因此将企图确认这个交易。</span><span id=Layer176></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b> 附注</b></font><p><font size=2 color=#3c3c3c face=arial>这是很罕见的情况,不过或客户端呼叫交易树根物件的IUnknown::Release,也同样会结束一个交易。预设COM runtime将这个状况视为根物件已呼叫SetComplete,因此将企图确认这个交易。</span><span id=Layer177></font></p><hr><p><font size=2 color=#3c3c3c face=arial>这代表的含意是在一个单独的交易中,控制权将会到客户端。只要客户端在交易逾时的时间点之前,呼叫一个有呼叫SetComplete或SetAbort method,所有的事都会运作的很好。不过假设客户端在活动的交易中将控制权交给使用者。由於使用者会有注意力不集中的现象,因此这个使用者可能正在和别人交谈,或决定要去喝一杯咖啡,或做些别的事,而这些事所花费的时间比交易逾时的时间还要更久。若发生这种情形,交易将会取消,或许会让这位使用者不高兴。结论是实际上在交易的过程中将控制权交给使用者是不安全的。取代的做法,每个交易应该尽可能简短。且每个交易应该实作一个可让使用者看到的要求。</span><span id=Layer178></font></p><p><font size=2 color=#3c3c3c face=arial>在交易的过程中不要将控制权交给使用者</span><span id=Layer179></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>在交易的过程中不要将控制权交给使用者</span><span id=Layer180></font></p><hr><p><font size=2 color=#3c3c3c face=arial>自动交易处理是很有用的,大部份的COM+应用程式都可享受它所带来的好处。不过建立有效率、可延展的企业级应用程式需要的更多,因此COM runtime提供的更多。举例来说,如下文所述,它提供管理物件状态等等有趣的服务。</span>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -