<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Florin Lazar - Consistency Checkpoint : MSDTC</title><link>http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx</link><description>Tags: MSDTC</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Phase0 in .Net System.Transactions</title><link>http://blogs.msdn.com/florinlazar/archive/2006/04/09/phase0-in-net-system-transactions.aspx</link><pubDate>Sun, 09 Apr 2006 23:20:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:572035</guid><dc:creator>florinlazar</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/572035.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=572035</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=572035</wfw:comment><description>&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;In a previous post (&lt;A href="http://blogs.msdn.com/florinlazar/archive/2006/01/29/518956.aspx" mce_href="http://blogs.msdn.com/florinlazar/archive/2006/01/29/518956.aspx"&gt;http://blogs.msdn.com/florinlazar/archive/2006/01/29/518956.aspx&lt;/A&gt;) I talked about Phase0 and some useful things it allows you to do. Although not referred as Phase0, phase 0 features are available in .Net System.Transactions in two forms. Actually in three, but the third is a derivate. I will make many references here to the &lt;A href="http://blogs.msdn.com/florinlazar/archive/2006/01/29/518956.aspx" mce_href="http://blogs.msdn.com/florinlazar/archive/2006/01/29/518956.aspx"&gt;previous post &lt;/A&gt;on Phase0 and thus I recommend reading it first.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;The first form where Phase 0 shows up is&amp;nbsp;through &lt;STRONG&gt;EnlistmentOptions.EnlistDuringPrepareRequired&lt;/STRONG&gt; that you can pass to EnlistVolatile or EnlistDurable methods. This allows you to create new enlistments during Prepare phase (and after Commit was called) and thus it allows you to create the caching resource manager (RM) discussed in the &lt;A href="http://blogs.msdn.com/florinlazar/archive/2006/01/29/518956.aspx" mce_href="http://blogs.msdn.com/florinlazar/archive/2006/01/29/518956.aspx"&gt;earlier post&lt;/A&gt;. To create a cache RM, you will first call EnlistVolatile with EnlistmentOptions.EnlistDuringPrepareRequired, and then, during Prepare you will connect to the database to write the updates. The connection to the database will usually call EnlistDurable on the transaction. Similar to Phase0 in the native DTC API, during the Prepare phase, one can enlist again passing EnlistmentOptions.EnlistDuringPrepareRequired which will issue another round of Prepare on that enlistment and so on.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;The second form comes with &lt;STRONG&gt;DependentTransaction&lt;/STRONG&gt;. You get a DependentTransaction by calling the DependentClone method on a transaction object. You can get the other two scenarios enabled by Phase0, “early commit protection” and “async programming” by tweaking the DependentCloneOption to RollbackIfNotComplete and BlockCommitUntilComplete respectively. Then, you signal&amp;nbsp;that the work is done&amp;nbsp;by calling the Complete method of this dependent transaction.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;Thus you will write the &lt;A href="http://blogs.msdn.com/florinlazar/archive/2006/01/29/518956.aspx" mce_href="http://blogs.msdn.com/florinlazar/archive/2006/01/29/518956.aspx"&gt;DoTransfer&lt;/A&gt; method in .Net as follows:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana color=#0000ff size=2&gt;int DoTransfer(int amount, Transaction tx)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // create the dependent clone&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DependentTransaction dtx = tx.DependentClone(DependentCloneOption. &lt;STRONG&gt;RollbackIfNotComplete&lt;/STRONG&gt;);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT face=Verdana color=#0000ff size=2&gt;DB1.OpenConnection(tx);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB1.DoDebit(amount);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB2.OpenConnection(tx);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB2.DoCredit(amount);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // signal work complete on the “phase0” enlistment&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dtx.Complete();&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;If the DependentTransaction is not Complete-ed before a Commit is issued by the client, the transaction will be aborted.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;The “third” derivate form is &lt;STRONG&gt;TransactionScope&lt;/STRONG&gt; itself. TransactionScope protects you against early commits by automatically handling under the covers a DependentTransaction with RollbackIfNotComplete. That is why TransactionScope is recommended for most of the transactions scenarios. Given this you can write with the same confidence the DoTransfer method as follows:&lt;BR&gt;&lt;BR&gt;&lt;FONT face=Verdana color=#0000ff&gt;int DoTransfer(int amount, Transaction tx)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // creating a TransactionScope by passing in the received transaction&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // this will set tx to be the ambient transaction and&amp;nbsp;create a&amp;nbsp;"rollback" dependent transaction&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;using(TransactionScope ts = new TransactionScope(tx))&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB1.OpenConnection(); // note that now OpenConnection is picking the transaction from the ambient context instead of passing it as a parameter&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB1.DoDebit(amount);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB2.OpenConnection();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB2.DoCredit(amount);&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;BR&gt;&lt;FONT face=Verdana color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ts.Complete();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;}&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;Other Scenarios enabled and/or made easier by DependentTransaction&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;&lt;STRONG&gt;The “Worker Threads Scenario”&lt;/STRONG&gt;&lt;BR&gt;This is explained both at &lt;/FONT&gt;&lt;A href="http://pluralsight.com/blogs/jimjohn/archive/2005/05/01/7923.aspx" mce_href="http://pluralsight.com/blogs/jimjohn/archive/2005/05/01/7923.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://pluralsight.com/blogs/jimjohn/archive/2005/05/01/7923.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; and &lt;/FONT&gt;&lt;A href="http://msdn2.microsoft.com/en-US/library/ms229976(VS.80).aspx" mce_href="http://msdn2.microsoft.com/en-US/library/ms229976(VS.80).aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://msdn2.microsoft.com/en-US/library/ms229976(VS.80).aspx&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;&lt;STRONG&gt;Passing transaction ownership in a sequence of threads&lt;BR&gt;&lt;/STRONG&gt;Described at &lt;/FONT&gt;&lt;A href="http://pluralsight.com/blogs/jimjohn/archive/2006/01/01/17769.aspx" mce_href="http://pluralsight.com/blogs/jimjohn/archive/2006/01/01/17769.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://pluralsight.com/blogs/jimjohn/archive/2006/01/01/17769.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt;.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;&lt;STRONG&gt;Async Programming&lt;BR&gt;&lt;/STRONG&gt;This is the scenario described in &lt;A href="http://blogs.msdn.com/florinlazar/archive/2006/01/29/518956.aspx" mce_href="http://blogs.msdn.com/florinlazar/archive/2006/01/29/518956.aspx"&gt;my previous post&lt;/A&gt; where the client asks asynchronously a service to do some work as part of the transaction, but doesn’t want/need to wait until the service completes the work. The code will look like the following in .Net:&lt;BR&gt;&lt;BR&gt;Client Code&lt;BR&gt;&lt;FONT face=Verdana color=#0000ff&gt;void MainFunction()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; using(TransactionScope ts = new TransactionScope())&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // dtx is a member of the current class of type DependentTransaction&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // its lifetime needs to be at least until the ack from the service is received&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.dtx = Transaction.Current.DependentClone(DependentCloneOption.&lt;STRONG&gt;BlockCommitUntilComplete&lt;/STRONG&gt;);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AsyncDoTransfer(tx, AckFromDoTransfer);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ts.Complete();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;BR&gt;void AckFromDoTransfer()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.dtx.Complete();&lt;BR&gt;}&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;Server Code&lt;BR&gt;&lt;FONT face=Verdana color=#0000ff&gt;void AsyncDoTransfer(tx, AckFromDoTransfer)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DependentTransaction dtx = tx.DependentClone(DependentCloneOption. &lt;STRONG&gt;BlockCommitUntilComplete&lt;/STRONG&gt;);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AckFromDoTransfer(); // the client can Commit safely from now on since I have dtx created on the service side&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // the dependent clone auto-created by TransactionScope doesn’t help in this scenario because it rollbacks on early commit while we need a blocking clone&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; using(TransactionScope ts = new TransactionScope(tx))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // doing the work that takes a lot of time&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB1.OpenConnection();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB1.DoDebit(amount);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB2.OpenConnection();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB2.DoCredit(amount);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ts.Complete();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// work if finished on the service so we can safely let the transaction continue&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dtx.Complete();&lt;BR&gt;}&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=572035" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/phase0/default.aspx">phase0</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/DependentTransaction/default.aspx">DependentTransaction</category></item><item><title>Our Own Forum is Now Live! Please Join Us at the &amp;quot;Transactions Programming Forum&amp;quot;</title><link>http://blogs.msdn.com/florinlazar/archive/2006/03/10/our-own-forum-is-now-live-please-join-us-at-the-quot-transactions-programming-forum-quot.aspx</link><pubDate>Sat, 11 Mar 2006 02:34:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:549107</guid><dc:creator>florinlazar</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/549107.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=549107</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=549107</wfw:comment><description>&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;I'm really happy to announce that our own forum, dedicated to transactions in Windows and .Net is now live at &lt;/FONT&gt;&lt;A href="http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=388&amp;amp;SiteID=1"&gt;&lt;FONT face=Tahoma size=2&gt;http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=388&amp;amp;SiteID=1&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;The RSS feed for the forum is &lt;/FONT&gt;&lt;A href="http://forums.microsoft.com/MSDN/rss.aspx?ForumID=388&amp;amp;Mode=0&amp;amp;SiteID=1"&gt;&lt;FONT face=Tahoma size=2&gt;http://forums.microsoft.com/MSDN/rss.aspx?ForumID=388&amp;amp;Mode=0&amp;amp;SiteID=1&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;I hope that by having a forum that is dedicated to Transactions technologies we can build a better channel for our customers to get quick and accurate answers to their questions. We encourage everyone in the community to participate in this forum.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;I look forward to us working together to make this forum a valuable resource for Transactions discussions.&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=549107" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Enterprise+Services/default.aspx">Enterprise Services</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/COM_2B00_/default.aspx">COM+</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Indigo/default.aspx">Indigo</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/forum/default.aspx">forum</category></item><item><title>Dedicated Site for Transactions on Microsoft.com</title><link>http://blogs.msdn.com/florinlazar/archive/2006/03/01/541177.aspx</link><pubDate>Wed, 01 Mar 2006 13:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:541177</guid><dc:creator>florinlazar</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/541177.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=541177</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=541177</wfw:comment><description>&lt;FONT face=Tahoma size=2&gt;In an effort to have a common place for all the transactions technologies we provide (and we started to have a good number of technologies that continues to grow), we have put together a webpage on Microsoft.com dedicated to transactions. The address is: &lt;/FONT&gt;&lt;A href="http://www.microsoft.com/windowsserver2003/appserver/transmgmt.mspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://www.microsoft.com/windowsserver2003/appserver/transmgmt.mspx&lt;/FONT&gt;&lt;/A&gt;&lt;BR&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=541177" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category></item><item><title>MSDTC: The Magic of Phase Zero (Phase0) – Or – When Using 2PC Transactions Is Not Enough</title><link>http://blogs.msdn.com/florinlazar/archive/2006/01/29/msdtc-the-magic-of-phase-zero-phase0-or-when-using-2pc-transactions-is-not-enough.aspx</link><pubDate>Mon, 30 Jan 2006 01:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:518956</guid><dc:creator>florinlazar</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/518956.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=518956</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=518956</wfw:comment><description>&lt;P&gt;The most known technique of implementing distributed transaction is the "two-phase commit" (2PC).&amp;nbsp;Here is a quick summary of how this technique works:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Active phase: After the transaction is created and before the "commit" message is issued by the creator, the transaction is in the "active" state. During this phase, resource managers can "enlist" and become part of the transaction. When "commit" is issued, the transaction moves to Phase1.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Phase1 (preparing phase): in which the superior transaction manager (TM), after receiving the Commit message from the creator of the transaction, "asks" the enlisted resource managers or the subordinate transaction managers to "prepare" for commit; if all respond with a successful "prepared" answer then the transaction moves to Phase 2, otherwise the transaction is aborted&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Phase 2 (committing phase) the superior TM writes a durable log entry about the status of the transaction and then starts sending "commit" messages to all the resource managers and subordinate TMs part of the transaction. In the case of any type of error (communication, computer crash etc), the superior TM will continue to send the "commit" messages until a successful "committed" message is received from all the participants. When all the participants responded "committed", the log entry corresponding to the current transaction is removed from the log and the transaction ends.&lt;/P&gt;
&lt;P&gt;In addition to the "two-phase commit" technique, MSDTC supports another phase called &lt;STRONG&gt;Phase Zero (Phase0)&lt;/STRONG&gt; which occurs after the creator of the transaction calls Commit and before Phase1 starts. To participate in Phase0 you need to enlist as a Phase0 participant: &lt;A href="http://msdn.microsoft.com/library/?url=/library/en-us/cossdk/htm/transactionphase0enlistment_6j04.asp?frame=true" mce_href="http://msdn.microsoft.com/library/?url=/library/en-us/cossdk/htm/transactionphase0enlistment_6j04.asp?frame=true"&gt;http://msdn.microsoft.com/library/?url=/library/en-us/cossdk/htm/transactionphase0enlistment_6j04.asp?frame=true&lt;/A&gt; and &lt;A href="http://msdn.microsoft.com/library/?url=/library/en-us/cossdk/htm/pgdtc_dev_8ldf.asp?frame=true" mce_href="http://msdn.microsoft.com/library/?url=/library/en-us/cossdk/htm/pgdtc_dev_8ldf.asp?frame=true"&gt;http://msdn.microsoft.com/library/?url=/library/en-us/cossdk/htm/pgdtc_dev_8ldf.asp?frame=true&lt;/A&gt;. MSDTC will always start with Phase0 and remain there until all the Phase0 participants responded. &lt;/P&gt;
&lt;P&gt;The great benefit of Phase0 is that during this phase, any type of enlistment (including Phase0) in the transaction it is still allowed. Once the transaction moves to Phase1, the new enlistments will be denied. Since you can create a new Phase0 enlistment during Phase0, MSDTC executes this phase in waves. After "commit" is issued, the TM will first send "Phase0Request" messages (&lt;A href="http://msdn.microsoft.com/library/en-us/cossdk/htm/itransactionphase0notifyasync_8ywk.asp" mce_href="http://msdn.microsoft.com/library/en-us/cossdk/htm/itransactionphase0notifyasync_8ywk.asp"&gt;http://msdn.microsoft.com/library/en-us/cossdk/htm/itransactionphase0notifyasync_8ywk.asp&lt;/A&gt;) to all known Phase0 enlistments. If all of them successfully replied Phase0Done (&lt;A href="http://msdn.microsoft.com/library/en-us/cossdk/htm/itransactionphase0enlistmentasync_5pt1.asp" mce_href="http://msdn.microsoft.com/library/en-us/cossdk/htm/itransactionphase0enlistmentasync_5pt1.asp"&gt;http://msdn.microsoft.com/library/en-us/cossdk/htm/itransactionphase0enlistmentasync_5pt1.asp&lt;/A&gt;), the TM will look for new Phase0 enlistments that occurred meanwhile and it will start another Phase0 wave if any is found and so on. Phase0 will end when no other new Phase0 enlistment is found after a wave. After Phase0 ends, the transaction moves to Phase1.&lt;/P&gt;
&lt;P&gt;Phase0 allows the following three scenarios: caching resource managers, protection against "early" commits and "safe" propagation of transactions in async programming.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Caching Resource Managers&lt;/STRONG&gt;&lt;BR&gt;Using a Phase0 enlistment, a middle-tier component can delay the connection to the database(s) as long as possible, acting as a cache to the requests from the client and thus reducing network traffic and database locks. This works great for those scenarios in which the client does many changes to the same data before it finally decides to end and save the work. When the client "ends" the work, the transaction is committed, and the TM issues a Phase0Request to the caching component. Before replying Phase0Done, the component will open all the necessary connections to the databases that need to be involved and it will persist the final data. These databases will now be "durably" enlisted in the transaction. After Phase0Done is received, the TM will continue with the 2PC and commit the transaction. See also &lt;A href="http://msdn.microsoft.com/library/?url=/library/en-us/cossdk/htm/pgdtc_dev_0y2b.asp?frame=true" mce_href="http://msdn.microsoft.com/library/?url=/library/en-us/cossdk/htm/pgdtc_dev_0y2b.asp?frame=true"&gt;http://msdn.microsoft.com/library/?url=/library/en-us/cossdk/htm/pgdtc_dev_0y2b.asp?frame=true&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Protection Against "Early" Commits&lt;BR&gt;&lt;/STRONG&gt;In general, 2PC transactions help to ensure integrity of data during different types of system errors. Using Phase0 you can also protect from badly written software. &lt;/P&gt;
&lt;P&gt;Let me give an example: let's say a transaction is created on the client side and then propagated to a middle tier component that is asked to do work as part of that transaction. The work that this component needs to do involves two databases, DB1 and DB2, as follows:&lt;/P&gt;
&lt;P&gt;int DoTransfer(int amount, transaction tx)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;DB1.OpenConnection(tx);&lt;BR&gt;&amp;nbsp; DB1.DoDebit(amount);&lt;BR&gt;&amp;nbsp; DB2.OpenConnection(tx);&lt;BR&gt;&amp;nbsp; DB2.DoCredit(amount);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;The component is using the received transaction to communicate with the two databases to ensure the integrity of its data. Both Debit and Credit operations need to be successful or none should occur. This looks great until now. But what if the client doesn't wait for DoTransfer to finish and calls Commit right after the DB1.DoDebit returned and before DB2.OpenConnection started? A badly written client can do that, maybe the programmer wanted to use multi-threading but didn't quite get it right. What will happen is that the component is left with inconsistent data in the databases, a debit operation that occurred without a credit operation. There is nothing wrong with the transaction itself; from the point of view of the 2PC transaction, only one enlistment occurred and that one responded successfully to both "prepare" and "commit" phases. It is the application logic that is wrong here. &lt;/P&gt;
&lt;P&gt;Can you protect against this type of situation? Yes, you can. One way is to write bug-free code, but mistakes happen. If you don't own the client code, the problem is even harder. The best solution is to use a Phase0 enlistment and modify the middle tier code as follows:&lt;/P&gt;
&lt;P&gt;int DoTransfer(int amount, transaction tx)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;EnlistPhase0(tx); //Creates a Phase0 enlistment with the transactions&lt;/P&gt;
&lt;P&gt;&amp;nbsp;DB1.OpenConnection(tx);&lt;BR&gt;&amp;nbsp;DB1.DoDebit(amount);&lt;BR&gt;&amp;nbsp;DB2.OpenConnection(tx);&lt;BR&gt;&amp;nbsp;DB2.DoCredit(amount);&lt;/P&gt;
&lt;P&gt;&amp;nbsp;SignalWorkCompletedToPhase0Enlistment(tx); // signals the Phase0 enlistment that the work was completed&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;Your Phase0 enlistment should start with a "WorkCompleted" flag set to false. The method SignalWorkCompletedToPhase0Enlistment mentioned above will set this flag to true. If a Phase0Request is received and the flag is still false, it means that the Commit was issued before the DoTransfer finished its work. At this point, you have two options: &lt;BR&gt;- one option (the recommended one when "early commits are not expected) is to abort the transaction and log some error; if you own the client code you might want to catch and fix these "early" commits&lt;BR&gt;- the other option is to hold the Phase0Request, received while DoTransfer is still doing work, until the flag becomes true and only then let the transaction continue by replying with Phase0Done; use this option when you expect to receive "early" commits as part of your system logic and flow.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Asynchronous Programming&lt;/STRONG&gt;&lt;BR&gt;This is very similar to the early commits scenarios mentioned above, but this time, the early commits are "by design". One can encounter scenarios where a piece of the application starts a transaction and delegates the work asynchronously to other parts of the application (a different thread of execution, a remote location) and without waiting for a response continues with committing the transaction. In these scenarios, we will choose the second option from above, the one that blocks the commit until work is finished. The code is similar:&lt;BR&gt;&amp;nbsp;Client code:&lt;BR&gt;&amp;nbsp;&amp;nbsp;Transaction tx = StartTransaction();&lt;BR&gt;&amp;nbsp;&amp;nbsp;AsyncDoTransfer(tx); // like create a separate thread and let it do the transfer operation etc&lt;BR&gt;&amp;nbsp;&amp;nbsp;SomeOtherAsyncWork(tx);&lt;BR&gt;&amp;nbsp;&amp;nbsp;CommitTransaction(tx);&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Server code:&lt;BR&gt;&amp;nbsp;&amp;nbsp;// inside AsyncDoTransfer that receives the transaction from the client&lt;BR&gt;&amp;nbsp;&amp;nbsp;EnlistPhase0AndBlock(tx); // if we get a Phase0Request we will block and wait until SignalWorkCompletedToPhase0Enlistment is called and only then reply with Phase0Done&lt;BR&gt;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp; DB1.OpenConnection(tx);&lt;BR&gt;&amp;nbsp; DB1.DoDebit(amount);&lt;BR&gt;&amp;nbsp; DB2.OpenConnection(tx);&lt;BR&gt;&amp;nbsp; DB2.DoCredit(amount);&lt;/P&gt;
&lt;P&gt;&amp;nbsp; SignalWorkCompletedToPhase0Enlistment(tx); // signals the Phase0 enlistment that the work was completed&lt;BR&gt;&amp;nbsp;&amp;nbsp;return;&lt;/P&gt;
&lt;P&gt;Looks nice and safe... Well, there is a problem even with this code. What if, Commit is called even before we are able to enlist in Phase0 in the AsyncDoTransfer method? We can end up again with some inconsistent data. The solution is to create some sort of acknowledgment from the server to the client saying that at least it got to the phase0 enlistment: "hey client, I know I'm slow and I will do your requested work later but here is my ack that you can Commit your transaction safely any time from now on". To accomplish this we will have to use phase0 enlistments on both the client and server side as follows:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Client Code:&lt;BR&gt;&amp;nbsp;&amp;nbsp;Void MainFunction()&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Transaction tx = StartTransaction();&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; EnlistPhase0AndBlock(tx); // if we get a Phase0Request we will block and wait until SignalWorkCompletedToPhase0Enlistment is called and only then reply with Phase0Done&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AsyncDoTransfer(tx, AckFromDoTransfer); // like sending an async message to a server and let it do the transfer operation etc&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CommitTransaction(tx);&amp;nbsp;&lt;BR&gt;&amp;nbsp; }&amp;nbsp; &lt;BR&gt;&amp;nbsp; void AckFromDoTransfer()&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SignalWorkCompletedToPhase0Enlistment(tx); // signals the Phase0 enlistment that the work was completed&amp;nbsp;&lt;BR&gt;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Server Code:&lt;BR&gt;&amp;nbsp;&amp;nbsp;void AsyncDoTransfer(tx, AckFromDoTransfer)&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;EnlistPhase0AndBlock(tx); // if we get a Phase0Request we will block and wait until SignalWorkCompletedToPhase0Enlistment is called and only then reply with Phase0Done&lt;BR&gt;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AckFromDoTransfer(); // the client can Commit safely the transaction from now, since I'm protected by phase 0&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // doing the work that takes a lot of time&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB1.OpenConnection(tx);&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;DB1.DoDebit(amount);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB2.OpenConnection(tx);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DB2.DoCredit(amount);&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SignalWorkCompletedToPhase0Enlistment(tx); // signals the Phase0 enlistment that the work was completed&lt;BR&gt;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;The phase0 enlistment on the client side will make sure that we keep the transaction in phase0 until we get all the acks from our servers. Look at this as a method to pass phase0 "ownership" from client to servers. &lt;/P&gt;
&lt;P&gt;All these work due to the "magic" of phase0 that allows "infinite" number of enlistments, until no new phase0 enlistments are being created and the existing ones replied with a successful Phase0Done. I compare the Phase0 enlistment to the AddRef method from the good old COM lifetime management. A Phase0 enlistment will call "AddRef" on the "active phase" of the transaction, while a Phase0Done will call "Release" on the counter. While the counter is higher than zero, the transaction will not be allowed to enter Phase1.&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=518956" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/phase0/default.aspx">phase0</category></item><item><title>SQL Server 2005 with COM+/DTC is first in a new TPC-C result</title><link>http://blogs.msdn.com/florinlazar/archive/2005/10/03/476729.aspx</link><pubDate>Tue, 04 Oct 2005 08:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:476729</guid><dc:creator>florinlazar</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/476729.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=476729</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=476729</wfw:comment><description>&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;The new results posted by Dell running SQL Server 2005 with COM+/DTC tops TPC-C by Price/Performance with .99 US$ price/tpmC: &lt;/FONT&gt;&lt;A href="http://www.tpc.org/tpcc/results/tpcc_price_perf_results.asp"&gt;&lt;FONT face=Tahoma size=2&gt;http://www.tpc.org/tpcc/results/tpcc_price_perf_results.asp&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;I can't wait to see some results with SQL Server 2005 combined with System.Transactions and our new "promotable transactions" (&lt;/FONT&gt;&lt;a href="http://blogs.msdn.com/florinlazar/archive/2005/05/12/416805.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://blogs.msdn.com/florinlazar/archive/2005/05/12/416805.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt;).&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=476729" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/COM_2B00_/default.aspx">COM+</category></item><item><title>Fast transactions with System.Transactions and Microsoft SQL Server 2000</title><link>http://blogs.msdn.com/florinlazar/archive/2005/09/29/fast-transactions-with-system-transactions-and-microsoft-sql-server-2000.aspx</link><pubDate>Fri, 30 Sep 2005 04:44:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:475546</guid><dc:creator>florinlazar</dc:creator><slash:comments>19</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/475546.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=475546</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=475546</wfw:comment><description>&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;The simplest way to use transactions today with Microsoft SQL Server 2000, using .Net Framework 2.0, is as follows:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT color=#00ffcc&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;static void Main(string[] args)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (TransactionScope ts = new TransactionScope())&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlConnection sqlConnection = new SqlConnection("connectionString");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sqlConnection.Open();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlCommand sqlCommand = new SqlCommand("INSERT INTO ...", sqlConnection);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sqlCommand.ExecuteNonQuery();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sqlConnection.Close();&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ts.Complete();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;If you really care about speed, you will notice that the performance decreases compared to when transactions are not used. If you do a little bit of investigation, you will notice that in fact a MSDTC distributed transaction is created and used when the code is executed (you can see this using Component Services snap-in). But why?&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;If you run the same code against Microsoft SQL Server 2005, the performance doesn't decrease when compared to a similar code that doesn't use transactions. Good, but you might not have SQL Server 2005 (yet). So, what can you do?&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;Let's first explain the "why". In order to take advantage of lightweight transaction manager (or LTM) that comes with System.Transactions, your durable resource manager, or database in this case, needs to support a mechanism called "promotable transactions". I talked about how this can be accomplished at &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/florinlazar/archive/2005/05/17/418595.aspx" mce_href="http://blogs.msdn.com/florinlazar/archive/2005/05/17/418595.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://blogs.msdn.com/florinlazar/archive/2005/05/17/418595.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; Since currently only SQL Server 2005 supports promotable transactions, when you use System.Transactions with SQL Server 2000, the lightweight transaction needs to be transformed into a MSDTC transaction, because this is the distributed transaction type that SQL Server 2000 understands. Having an MSDTC transaction involved, means there is some additional cost, and that is why you are seeing the perf hit. Just to make sure we are on sync on this, the perf hit is only when you compare it to the scenario that is not using transactions. If you compare System.Transactions with EnterpriseServices/COM+ scenarios using transactions, the perf is improved with System.Transactions.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;And now, let's go over on what can you do, if you want to use System.Transactions with no perf hit, in a scenario where you only talk to a database server (Microsoft SQL Server 2000) and you might also involve volatile transacted resources, like a transacted hashtable. The solution is to use an "adapter" that enlists with the System.Transactions transaction using PSPE (&lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/florinlazar/archive/2005/05/17/418595.aspx" mce_href="http://blogs.msdn.com/florinlazar/archive/2005/05/17/418595.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://blogs.msdn.com/florinlazar/archive/2005/05/17/418595.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt;) and coordinates the connection to the SQL Server using a SQL "local transaction". The code will have to look like this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;&lt;FONT color=#00ffcc&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;static void Main(string[] args)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (TransactionScope ts = new TransactionScope())&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlConnection sqlConnection = new SqlConnection("connectionString&lt;STRONG&gt;;Enlist=false&lt;/STRONG&gt;");&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;DatabaseTransactionAdapter dbAdapter = new DatabaseTransactionAdapter(sqlConnection);&lt;BR&gt;&lt;/STRONG&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sqlConnection.Open();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;STRONG&gt;dbAdapter.Begin();&lt;/STRONG&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlCommand sqlCommand = new SqlCommand("INSERT INTO ...", sqlConnection);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;sqlCommand.Transaction = (SqlTransaction)dbAdapter.Transaction;&lt;BR&gt;&lt;/STRONG&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sqlCommand.ExecuteNonQuery();&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ts.Complete();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;In addition to the changes/additions in bold, you should also observe that “sqlConnection.Close();” was removed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;Now let’s dive into the details of the adapter. First, since the adapter will handle the connection to the SQL Server, you will have to specify in the connection string “Enlist=false”, thus telling to the SQL client to not enlist in the transaction, because this will determine the creation of a MSDTC transaction for reasons mentioned above. And you also must not close the connection, because the connection should stay open until the transaction is completed, which happens after the “using” statement ends. The adapter will take ownership of the connection lifetime and close it when it is done with it.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;When Begin is called on the adapter, the adapter will enlist with the System.Transactions transaction, in other words, Transaction.Current, using EnlistPromotableSinglePhase. Later, LTM will call Initialize on the enlistment interface, and that is the time when the bridge to the SQL Server is established; the adapter will start an internal SQL transaction on the connection provided in the constructor using SqlConnection.BeginTransaction().&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;An additional step that might look unnecessary, at least for me, is that you need to set the internal SQL transaction from the connection to the sqlCommand.Transaction property. Manually. Why SqlCommand can’t get that automatically from the SqlConnection object, I don’t know. Maybe an expert in SQL objects can jump in and explain. And that is why the adapter needs to publish the SQL transaction in a property.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;When the transaction completes, after exiting the using statement, LTM will notify the adapter through the IPromotableSinglePhaseNotification interface to commit or abort the transaction. Consequenlty the adapter will commit or abort the internal SQL transaction.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;John Doty from my team, created a set of classes that does exactly this (the adapter works for both resource managers using IDbConnection and the MSMQ resource manager). They are available for download at &lt;/FONT&gt;&lt;A href="http://download.microsoft.com/download/B/D/0/BD0D4D33-89DC-497E-B3F2-95871A03A5F7/PrivateTransactionAdapter.msi" mce_href="http://download.microsoft.com/download/B/D/0/BD0D4D33-89DC-497E-B3F2-95871A03A5F7/PrivateTransactionAdapter.msi"&gt;&lt;FONT face=Tahoma size=2&gt;http://download.microsoft.com/download/B/D/0/BD0D4D33-89DC-497E-B3F2-95871A03A5F7/PrivateTransactionAdapter.msi&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; The installer will expand a TransactionAdapter.cs in C:\Documents and Settings\&amp;lt;currentUser&amp;gt;\My Documents\MSDN\Private Transaction Adapter. All you have to do is link the file to your project and use the adapter as described above. &lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=475546" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/SQL+2000/default.aspx">SQL 2000</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/PSPE/default.aspx">PSPE</category></item><item><title>DTCPing: Troubleshooting MSDTC Connectivity Issues</title><link>http://blogs.msdn.com/florinlazar/archive/2005/09/16/469064.aspx</link><pubDate>Fri, 16 Sep 2005 20:31:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:469064</guid><dc:creator>florinlazar</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/469064.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=469064</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=469064</wfw:comment><description>&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;In today's world, security hardening is causing many headaches to software developers and admins. Especially when you have an application that needs to go beyond the boundaries of the local machine. MSDTC is a distributed app by definition and thus, getting transacted app that uses MSDTC to work in your network is not as easy as one would expect. You either get "New transaction cannot enlist in specified transaction coordinator" or 8004d00a.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;There is a tool that can help you troubleshoot MSDTC connectivity issues, and that tool is called DTCPing: &lt;/FONT&gt;&lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=5e325025-4dcd-4658-a549-1d549ac17644&amp;amp;DisplayLang=en"&gt;&lt;FONT face=Tahoma size=2&gt;http://www.microsoft.com/downloads/details.aspx?FamilyID=5e325025-4dcd-4658-a549-1d549ac17644&amp;amp;DisplayLang=en&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;It was initially created to troubleshoot firewall issues: &lt;/FONT&gt;&lt;A href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q306843"&gt;&lt;FONT face=Tahoma size=2&gt;http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q306843&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; This KB article also gives you instructions on how to use DTCPing.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;Most common errors that block MSDTC connectivity in a network are:&lt;BR&gt;&amp;nbsp;1. MSDTC Security settings are not configured properly: &lt;/FONT&gt;&lt;a href="http://blogs.msdn.com/florinlazar/archive/2004/06/18/159127.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://blogs.msdn.com/florinlazar/archive/2004/06/18/159127.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;BR&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;2. MSDTC is not in the exception list in the firewall&lt;BR&gt;&amp;nbsp;3. The two machines involved in the transaction cannot see each other by the NetBIOS name. Try ping-ing the machines by name. If that fails, MSDTC will fail. You can solve this by updating your system32\drivers\etc\hosts file.&lt;BR&gt;&amp;nbsp;4. If the machines were imaged improperly, the CID for MSDTC under HKEY_CLASSES_ROOT\CID may be the same on the two machines, while they need to be unique. The KB 306843 mentioned above gives the instructions to correct this issue.&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=469064" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category></item><item><title>Transactions Sessions at PDC 2005</title><link>http://blogs.msdn.com/florinlazar/archive/2005/09/14/transactions-sessions-at-pdc-2005.aspx</link><pubDate>Wed, 14 Sep 2005 20:31:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:466237</guid><dc:creator>florinlazar</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/466237.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=466237</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=466237</wfw:comment><description>&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;If you are at PDC this year, don't forget to attend the sessions related to transactions. An easy way to find these sessions is to go to &lt;/FONT&gt;&lt;A href="http://commnet1.microsoftpdc.com/content/sessions.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://commnet1.microsoftpdc.com/content/sessions.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt; and search by Keyword="transaction".&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;I especially recommend the session called "FUN320 - Windows &lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:place w:st="on"&gt;Vista&lt;/st1:place&gt; &amp;amp; "Longhorn" Server: Improving Reliability Using System.Transactions and the Transactional NTFS and Registry".&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Jim Johnson, our architect for transactions is presenting this session together with Dana Groff, the program manager in Core File Services focusing on transaction technologies.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;Here is the full list:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;FUN320&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Windows &lt;st1:place w:st="on"&gt;Vista&lt;/st1:place&gt; &amp;amp; "Longhorn" Server: Improving Reliability Using System.Transactions and the Transactional NTFS and Registry &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Day/Time: Thursday, September 15 5:15 PM- 6:30 PM Room: 406 AB&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Speaker(s): Dana Groff, Jim Johnson&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Session Type(s): Breakout&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Session Level(s): 300&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Track(s): Fundamentals&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;You can build significantly more reliable applications by using the expanded and enhanced classes in the System.Transactions namespace. This session covers how to use new transaction-oriented programming techniques for application stability and robustness. Learn about the new systems in Windows Vista and "Longhorn" Server for supporting Transacted Files (TxF) and Transacted Registry (TxR) operations in both native and managed code. &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT size=1&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;FUN323&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Microsoft Research: Future Possibilities in Concurrency &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Day/Time: Friday, September 16 8:30 AM- 9:45 AM Room: 406 AB&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Speaker(s): Tim Harris&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Session Type(s): Breakout&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Session Level(s): 300&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Track(s): Fundamentals&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Learn about the investment Microsoft Research is making in future languages and tools to help write software that will gain the maximum benefit from tomorrow's multi-processor/multi-core hardware. In this session, we start by introducing some of the tools and techniques we've developed for tracking down and preventing bugs in multi-threaded software. We then turn to the language features that we're prototyping in research: our work on transactional memory is developing a programming model where data can be shared directly between threads without needing to worry about locking or low-level deadlocks; our work on synchronization is leading to a unified abstraction for co-ordination between threads and between processes. We'll demo some of our prototype systems, showing how these techniques can lead to software which is not only easier to develop, but which can scale from uniprocessors up to highly parallel systems.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT size=1&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Distributed Atomic Transactions - Wishful Thinking? &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Day/Time: Tuesday, September 13 9:00 PM- 10:00 PM Room: 511 C&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Session Type(s): Birds of a Feather&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Session Level(s): 300&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Web Services, via SOAP, is the preferred choice of doing wide-reaching distributed communications today. However, one of the few factors that has hindered its adoption in the enterprise today is its lack of ability to handle transactions between remote un-trusted (independent) boundaries. There are two schools of thought today with regards to transactions --- The Atomic Way or The Compensating Way which pretty much takes out the atomicity of ACID. Indigo supports WS-AT via Microsoft DTC. Will this be widely adopted in the enterprise collaboration space? Or are we living in Fool's Paradise? &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT size=1&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;COM307&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Windows Communications Foundation ("Indigo"): Writing Reliable and Transacted Distributed Applications &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Day/Time: Wednesday, September 14 3:15 PM- 4:30 PM Room: 403 AB&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Speaker(s): Shy Cohen&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Session Type(s): Breakout&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Session Level(s): 300&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Track(s): Communications&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;What do you do when your network connection breaks half-way through a request? How do you synchronize state changes across different Web services? How do you overcome a system crash without losing important messages? Windows Communications Foundation (formerly codename "Indigo") provides simple and powerful reliability mechanisms that allow you to easily address these types of network and application issues. Take an in-depth look at reliable sessions, queues, and distributed transactions, and how these technologies are used to achieve reliable, transacted communication. &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT size=1&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;COM202&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Windows Communications Foundation ("Indigo"): A Lap around the Windows Communications Foundation &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Day/Time: Tuesday, September 13 1:00 PM- 2:15 PM Room: Halls C &amp;amp; D (Petree Hall)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Speaker(s): Omri Gazitt&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Session Type(s): Breakout&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Session Level(s): 200&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Track(s): Communications&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;Windows Communications Foundation (formerly codename "Indigo") is Microsoft's new platform technology for building distributed applications, bringing the best of ASP.NET Web services, .NET Remoting, Enterprise Services, WSE, and System.Messaging into one unified framework. This session introduces the core concepts in the Windows Communications Foundation programming model-addresses, bindings, contracts, and behaviors-and presents the Windows Communications Foundation feature set through the lens of these concepts. This session covers security, reliable messaging, transactions, queues, hosting, transports, interop/integration, and more. If you have never seen an introduction to Windows Communication Framework, this session is for you.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=1&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The slides from these sessions are currently available at &lt;/FONT&gt;&lt;A href="http://commnet.microsoftpdc.com/content/downloads.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://commnet.microsoftpdc.com/content/downloads.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=466237" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Enterprise+Services/default.aspx">Enterprise Services</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/COM_2B00_/default.aspx">COM+</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Indigo/default.aspx">Indigo</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/PDC/default.aspx">PDC</category></item><item><title>WS Specs for Transactions Updated</title><link>http://blogs.msdn.com/florinlazar/archive/2005/08/22/454872.aspx</link><pubDate>Tue, 23 Aug 2005 03:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:454872</guid><dc:creator>florinlazar</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/454872.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=454872</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=454872</wfw:comment><description>&lt;FONT face=Tahoma size=2&gt;The WS specifications related to Transactions (WS-Coordination, WS-AtomicTransaction and WS-BusinessActivity) have just been updated. They are available at &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/webservices/webservices/understanding/specs/default.aspx?pull=/library/en-us/dnglobspec/html/wsatspecindex.asp"&gt;&lt;FONT face=Tahoma size=2&gt;http://msdn.microsoft.com/webservices/webservices/understanding/specs/default.aspx?pull=/library/en-us/dnglobspec/html/wsatspecindex.asp&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt;.&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=454872" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Indigo/default.aspx">Indigo</category></item><item><title>Writing a resource manager that supports promotable transactions (or Promotable Single Phase Enlistment aka PSPE) in System.Transactions</title><link>http://blogs.msdn.com/florinlazar/archive/2005/05/17/writing-a-resource-manager-that-supports-promotable-transactions-or-promotable-single-phase-enlistment-aka-pspe-in-system-transactions.aspx</link><pubDate>Tue, 17 May 2005 17:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:418595</guid><dc:creator>florinlazar</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/418595.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=418595</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=418595</wfw:comment><description>&lt;P&gt;A key feature that targets performance in System.Transactions is the Promotable Single Phase Enlistment. It allows a durable resource manager (RM) to host and "own" a transaction that can later be promoted to a distributed transaction (or MSDTC transaction) if necessary. This specific resource manager usually has its own internal non distributed transactions and it needs to support changing those transactions to distributed transactions at runtime.&lt;/P&gt;
&lt;P&gt;The overview of steps involved in PSPE is:&lt;BR&gt;1. The RM proxy enlists for PSPE using Transaction.EnlistPromotableSinglePhase. If the enlistment succeeds, the RM usually creates its internal transaction and associates it with the System.Transactions transaction. The notification are later sent to the RM proxy using the IPromotableSinglePhaseNotification interface&lt;BR&gt;2. If the System.Transactions transaction never requires a promotion (see previous post &lt;A href="http://blogs.msdn.com/florinlazar/archive/2005/05/12/416805.aspx" mce_href="http://blogs.msdn.com/florinlazar/archive/2005/05/12/416805.aspx"&gt;http://blogs.msdn.com/florinlazar/archive/2005/05/12/416805.aspx&lt;/A&gt;) then, when the transaction is committed, the RM proxy will receive a SinglePhaseCommit, at which point it can commit the internal transaction that was initially created&lt;BR&gt;3. If the System.Transactions transaction needs to be promoted (to support multiple RMs for instance), then System.Transactions will ask the RM to promote the transaction to a distributed transaction. The RM will have to promote the internal transaction to an MSDTC transaction, and associate it with the work already done. Later, when System.Transactions will commit its transaction, it will send a SinglePhaseCommit notification to the RM proxy and the RM will have to commit the distributed transaction that it created during promotion.&lt;/P&gt;
&lt;P&gt;Please note that at step 1, I had an "if the PSPE enlistment succeeds" condition. This means that PSPE is not always allowed by System.Transactions. The cases when this can happen are: 1) the transaction is already a distributed transaction or 2) another RM has already done a PSPE enlistment. If the PSPE enlistment fails, the RM will have to follow the regular rules for enlistment (marshal the transaction to the RM and enlist using DurableEnlist).&lt;/P&gt;
&lt;P&gt;Let's look at code now. I will have a client and a server communicating using remoting:&lt;/P&gt;
&lt;P&gt;&amp;lt;client.cs&amp;gt;&lt;BR&gt;&lt;PRE class=csharpcode&gt;using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Transactions;

namespace PSPEClient
{
    class Client
    {
        static void Main(string[] args)
        {
            using (TransactionScope ts = new TransactionScope())
            {
                /*section1begin
                DurableRM durableRM = new DurableRM();
                durableRM.OpenConnection();
                durableRM.DoWork();
                /*section1end*/
                
                DatabaseProxy dbProxy = new DatabaseProxy();
                dbProxy.OpenConnection();
                dbProxy.DoWork();
                
                /*section2begin
                DurableRM durableRM = new DurableRM();
                durableRM.OpenConnection();
                durableRM.DoWork();
                /*section2end*/
                
                ts.Complete();
            }
            System.Console.ReadLine();
        }
        
        class DatabaseProxy
        {
            private PSPEServer.PSPEDatabaseServer db;
            private InternalRM internalRM;
            
            public void OpenConnection()
            {
                System.Console.WriteLine("DatabaseProxy.OpenConnection");
                // connecting to the remote database
                TcpChannel tcpChannel = new TcpChannel();
                ChannelServices.RegisterChannel(tcpChannel);
                this.db = (PSPEServer.PSPEDatabaseServer)Activator.GetObject(
                    typeof(PSPEServer.PSPEDatabaseServer), "tcp://localhost:8085/MyDatabase");
                if (null == db)
                {
                    System.Console.WriteLine("Cannot connect to the server");
                }
                else
                {
                    System.Console.WriteLine("Internal tx id:" + db.Connect());
                }
                
                // enlisting in the transaction
                if (null != this.internalRM)
                {
                    throw new System.Exception("we don't support multiple connections, this is just a sample");
                }
                this.internalRM = new InternalRM(db);
                this.internalRM.Enlist();
            }
            
            public void DoWork()
            {
                System.Console.WriteLine("DatabaseProxy.DoWork");
                db.DoWork();
            }
            
            class InternalRM : IPromotableSinglePhaseNotification
            {
                #region IPromotableSinglePhaseNotification Members
                
                // This member will be called during the call to EnlistPromotableSinglePhase
                // The RM will usually allocate its internal transaction state here
                public void Initialize()
                {
                    System.Console.WriteLine("InternalRM.Initialize");
                }
                
                // This method will be called if the RM should Rollback the
                // transaction.  Note that this method will be called even if
                // the transaction has been promoted to a distributed transaction.
                public void Rollback(SinglePhaseEnlistment singlePhaseEnlistment)
                {
                    System.Console.WriteLine("InternalRM.Rollback");
                    db.RollbackWork();
                    singlePhaseEnlistment.Aborted();
                }
                
                // This method will be called when the RM should Commit the
                // transaction.  Note that this method will be called even if
                // the transaction has actually been promoted to a distributed
                // transaction.
                public void SinglePhaseCommit(SinglePhaseEnlistment singlePhaseEnlistment)
                {
                    System.Console.WriteLine("InternalRM.SinglePhaseCommit");
                    db.CommitWork();
                    singlePhaseEnlistment.Committed();
                }
                
                #endregion
            
                #region ITransactionPromoter Members
                
                // This method will be called if System.Transactions
                // determines that the transaction actually needs the support of
                // a fully distributed transaction manager.  The return value of
                // this method is a promoted representation of the transaction
                // usually in the form of transmitter/receiver propagation token
                public byte[] Promote()
                {
                    System.Console.WriteLine("InternalRm.Promote");
                    return db.Promote();
                }
                
                #endregion
            
                private PSPEServer.PSPEDatabaseServer db;
                
                public InternalRM(PSPEServer.PSPEDatabaseServer db)
                {
                    this.db = db;
                }
                
                public void Enlist()
                {
                    System.Console.WriteLine("InternalRM.Enlist");
                    if (null != Transaction.Current)
                    {
                        if (!Transaction.Current.EnlistPromotableSinglePhase(this))
                        {
                            System.Console.WriteLine("PSPE failed, doing regular Enlist");
                            // PSPE failed; we need to use the regular enlistment
                            db.Enlist(TransactionInterop.GetTransmitterPropagationToken(Transaction.Current));
                        }
                    }
                }
            }
        }
     
        class DurableRM : IEnlistmentNotification
        {
            
            #region IEnlistmentNotification Members
            
            public void Commit(Enlistment enlistment)
            {
                System.Console.WriteLine("DurableRM.Commit");
                enlistment.Done();
            }
            
            public void InDoubt(Enlistment enlistment)
            {
                System.Console.WriteLine("DurableRM.InDoubt");
                throw new Exception("The method or operation is not implemented.");
            }
            
            public void Prepare(PreparingEnlistment preparingEnlistment)
            {
                System.Console.WriteLine("DurableRM.Prepare");
                // first a durable RM will log preparingEnlistment.RecoveryInformation(), but this is just a sample
                preparingEnlistment.Prepared();
            }
            
            public void Rollback(Enlistment enlistment)
            {
                System.Console.WriteLine("DurableRM.Rollback");
                enlistment.Done();
            }
            
            #endregion
            
            public void OpenConnection()
            {
                System.Console.WriteLine("DurableRM.OpenConnection and enlist durable");
                if (null != Transaction.Current)
                {
                    Transaction.Current.EnlistDurable(Guid.NewGuid(), this, EnlistmentOptions.None);
                }
            }
            public void DoWork()
            {
                System.Console.WriteLine("DurableRM - DoWork");
            }
        }
    }
}
&lt;/PRE&gt;&amp;lt;/client.cs&amp;gt;&lt;BR&gt;&amp;lt;server.cs&amp;gt;&lt;BR&gt;&lt;PRE class=csharpcode&gt;using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Transactions;
using System.Diagnostics;
 
namespace PSPEServer
{
    class Server
    {
        static void Main(string[] args)
        {
            TcpChannel tcpChannel = new TcpChannel(8085);
            ChannelServices.RegisterChannel(tcpChannel);
            RemotingConfiguration.RegisterWellKnownServiceType(Type.GetType("PSPEServer.PSPEDatabaseServer"),
                "MyDatabase", WellKnownObjectMode.Singleton);
            System.Console.WriteLine("Server running...");
            System.Console.ReadLine();
        }
    }
 
    public class PSPEDatabaseServer : MarshalByRefObject
    {
        private int internalTxID = 0;
        private CommittableTransaction tx;
        private InternalServerRM internalServerRM;

        public int Connect()
        {
            System.Console.WriteLine("client connected");
            return ++internalTxID;
        }

        public void DoWork()
        {
            System.Console.WriteLine("PSPEDBServer.DoWork");
        }

        public byte[] Promote()
        {
            System.Console.WriteLine("PSPEDBServer.Promote");
            this.tx = new CommittableTransaction();
            Debug.Assert(this.internalServerRM == null);
            // the following statement will cause the transaction to be promoted to MSDTC
            byte[] txToken = TransactionInterop.GetTransmitterPropagationToken(this.tx);
            Enlist(txToken);
            return txToken;
        }

        public void CommitWork()
        {
            System.Console.WriteLine("PSPEDBServer.CommitWork");
            if (tx != null)
            {
                // we have a distributed transaction, and so we have to commit it
                tx.Commit();
            }
            else
            {
                // we only have an internal tx
                System.Console.WriteLine("committing internal tx:" + internalTxID);
            }
        }

        public void RollbackWork()
        {
            System.Console.WriteLine("PSPEDBServer.RollbackWork");
            if (tx != null)
            {
                // we have a distributed transaction, and so we have to rollback it
                tx.Rollback();
            }
            else
            {
                // we only have an internal tx
                System.Console.WriteLine("aborting internal tx:" + internalTxID);
            }        
        }

        public void Enlist(byte[] txToken)
        {
            System.Console.WriteLine("PSPEDBServer.Enlist");
            this.internalServerRM = new InternalServerRM();
            this.internalServerRM.Enlist(txToken);
        }

        private class InternalServerRM : ISinglePhaseNotification
        {

            #region ISinglePhaseNotification Members

            public void SinglePhaseCommit(SinglePhaseEnlistment singlePhaseEnlistment)
            {
                System.Console.WriteLine("InternalServerRM.SPC");
                singlePhaseEnlistment.Committed();
            }

            #endregion

            #region IEnlistmentNotification Members

            public void Commit(Enlistment enlistment)
            {
                System.Console.WriteLine("InternalServerRM.Commit");
                enlistment.Done();
            }

            public void InDoubt(Enlistment enlistment)
            {
                System.Console.WriteLine("InternalServerRM.InDoubt");
                throw new Exception("The method or operation is not implemented.");
            }

            public void Prepare(PreparingEnlistment preparingEnlistment)
            {
                System.Console.WriteLine("InternalServerRM.Prepare");
                // first a durable RM will log preparingEnlistment.RecoveryInformation(), but this is just a sample
                preparingEnlistment.Prepared();
            }

            public void Rollback(Enlistment enlistment)
            {
                System.Console.WriteLine("InternalServerRM.Rollback");
                enlistment.Done();
            }

            #endregion

            private Guid rmGuid = new Guid("{B14FF9BB-8419-4dbc-A78C-3C1453D60AC4}");

            public void Enlist(byte[] txToken)
            {
                System.Console.WriteLine("InternalServerRM.Enlist");
                TransactionInterop.GetTransactionFromTransmitterPropagationToken(txToken).EnlistDurable(
                    this.rmGuid, this, EnlistmentOptions.None);
            }
        }
    }
}&lt;/PRE&gt;&amp;lt;/server.cs&amp;gt; 
&lt;P&gt;If we run the code, with only the PSPE enlistment, System.Transactions is managing the transaction and MSDTC is never involved; we get the following outputs:&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;lt;client&amp;gt;&lt;BR&gt;DatabaseProxy.OpenConnection&lt;BR&gt;Internal tx id:1&lt;BR&gt;InternalRM.Enlist&lt;BR&gt;InternalRM.Initialize&lt;BR&gt;DatabaseProxy.DoWork&lt;BR&gt;InternalRM.SinglePhaseCommit&lt;BR&gt;&amp;lt;/client&amp;gt;&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;lt;server&amp;gt;&lt;BR&gt;Server running...&lt;BR&gt;client connected&lt;BR&gt;PSPEDBServer.DoWork&lt;BR&gt;PSPEDBServer.CommitWork&lt;BR&gt;committing internal tx:1&lt;BR&gt;&amp;lt;/server&amp;gt;&lt;BR&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If we enlist a durable RM after the PSPE enlistment (uncomment section 2), the transaction is promoted to MSDTC when the durable enlistment is done and the outputs are:&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;lt;client&amp;gt;&lt;BR&gt;DatabaseProxy.OpenConnection&lt;BR&gt;Internal tx id:1&lt;BR&gt;InternalRM.Enlist&lt;BR&gt;InternalRM.Initialize&lt;BR&gt;DatabaseProxy.DoWork&lt;BR&gt;DurableRM.OpenConnection and enlist durable&lt;BR&gt;InternalRm.Promote&lt;BR&gt;DurableRM - DoWork&lt;BR&gt;InternalRM.SinglePhaseCommit&lt;BR&gt;DurableRM.Prepare&lt;BR&gt;DurableRM.Commit&lt;BR&gt;&amp;lt;/client&amp;gt;&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;lt;server&amp;gt;&lt;BR&gt;Server running...&lt;BR&gt;client connected&lt;BR&gt;PSPEDBServer.DoWork&lt;BR&gt;PSPEDBServer.Promote&lt;BR&gt;PSPEDBServer.Enlist&lt;BR&gt;InternalServerRM.Enlist&lt;BR&gt;PSPEDBServer.CommitWork&lt;BR&gt;InternalServerRM.Prepare&lt;BR&gt;InternalServerRM.Commit&lt;BR&gt;&amp;lt;/server&amp;gt;&lt;BR&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;And finally, if we enlist a durable RM before the PSPE enlistment (uncomment section 1), the PSPE enlistment will fail and thus the RM will have to follow the regular enlistment procedures. The outputs in this case are:&lt;/P&gt;
&lt;P&gt;&amp;lt;client&amp;gt;&lt;BR&gt;DurableRM.OpenConnection and enlist durable&lt;BR&gt;DurableRM - DoWork&lt;BR&gt;DatabaseProxy.OpenConnection&lt;BR&gt;Internal tx id:1&lt;BR&gt;InternalRM.Enlist&lt;BR&gt;PSPE failed, doing regular Enlist&lt;BR&gt;DatabaseProxy.DoWork&lt;BR&gt;DurableRM.Prepare&lt;BR&gt;DurableRM.Commit&lt;BR&gt;&amp;lt;/client&amp;gt;&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;lt;server&amp;gt;&lt;BR&gt;Server running...&lt;BR&gt;client connected&lt;BR&gt;PSPEDBServer.Enlist&lt;BR&gt;InternalServerRM.Enlist&lt;BR&gt;PSPEDBServer.DoWork&lt;BR&gt;InternalServerRM.Prepare&lt;BR&gt;InternalServerRM.Commit&lt;BR&gt;&amp;lt;/server&amp;gt;&lt;BR&gt;&amp;nbsp;&lt;BR&gt;NOTE: the goal of my sample was to show the use of PSPE. For simplicity, I ignored dealing with the recovery (I will follow up with another post where I will target Durable Enlistments and recovery).&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=418595" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/promotable+transactions/default.aspx">promotable transactions</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/PSPE/default.aspx">PSPE</category></item><item><title>What is the Lighweight Transaction Manager and why do you need to know about it</title><link>http://blogs.msdn.com/florinlazar/archive/2005/05/12/416805.aspx</link><pubDate>Thu, 12 May 2005 13:49:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:416805</guid><dc:creator>florinlazar</dc:creator><slash:comments>14</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/416805.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=416805</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=416805</wfw:comment><description>&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;A "hidden" feature available in System.Transactions is the Lightweight Transaction Manager (LTM). It provides support for light weight transactions that live in the current appdomain. The LTM acts as a façade layer for all the transactions started in System.Transactions and based on a set of rules, it will "fallback" to an MSDTC distributed transaction when it is necessary. I call it "fallback" because there is some performance penalty that you need to pay when this happens: the transaction will span beyond the appdomain and there will be cross-process messages that will be sent, since MSDTC resides in a different process. (Note that from the TM functionality point of view, you can also call this a "promotion", since the MSDTC is a more general purpose and more complete TM). The fallback/promotion happens behind the scenes without any action required from the application developer.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;As long as the LTM deals with volatile resources (that enlist using Transaction.EnlistVolatile) and with at most one durable resource that supports single phase notifications (this resource enlists with Transaction.EnlistDurable and implements ISinglePhaseNotification) then the transaction remains in the ownership of LTM. The LTM restricts itself only to those resources that live in the same appdomain and for which "logging" (writing the transaction outcome to the disk) is not required.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;The fallback will take place and the LTM will transfer the ownership of the transaction to MSDTC if any of the following is true:&lt;BR&gt;- at least one durable resource that doesn't support single phase notifications is enlisted in the transaction&lt;BR&gt;- at least two durable resources that support single phase notifications are enlisted in the transaction&lt;BR&gt;- a request to "marshal" the transaction to a different appdomain or different process is done.&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face=Tahoma size=2&gt;&lt;BR&gt;In between the LTM transaction and MSDTC transaction there is one intermediary type of transaction that we sometimes call it "database transaction" that is made available through the Promotable Single Phase Enlistment. PSPE is another important mechanism in System.Transactions for performance optimization. It allows a remote durable resource, located in a different appdomain/process/machine, to participate in the LTM transaction without causing it to "fallback" to an MSDTC transaction.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;Since the LTM is a "hidden" feature, the only reason for which you need to know about its existence is when you care a lot about performance. You will want to delay or avoid&amp;nbsp;the fallback to MSDTC as much as possible to gain performance and for that you need to know how and when the fallback is triggered.&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=416805" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category></item><item><title>What do you want to know about transactions?</title><link>http://blogs.msdn.com/florinlazar/archive/2005/05/07/415406.aspx</link><pubDate>Sun, 08 May 2005 00:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:415406</guid><dc:creator>florinlazar</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/415406.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=415406</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=415406</wfw:comment><description>&lt;FONT face=Tahoma size=2&gt;Please don't hesitate to send me your suggestions or questions or topics you would like to be discussed in this blog. You can post a comment to this post or use &lt;/FONT&gt;&lt;a href="http://blogs.msdn.com/florinlazar/contact.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://blogs.msdn.com/florinlazar/contact.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; to let me know. I'll prioritize the list and cover as much as I can.&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=415406" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Enterprise+Services/default.aspx">Enterprise Services</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/COM_2B00_/default.aspx">COM+</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Microsoft+Windows/default.aspx">Microsoft Windows</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Indigo/default.aspx">Indigo</category></item><item><title>Blog on Transactional NTFS</title><link>http://blogs.msdn.com/florinlazar/archive/2005/04/27/412486.aspx</link><pubDate>Wed, 27 Apr 2005 13:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:412486</guid><dc:creator>florinlazar</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/412486.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=412486</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=412486</wfw:comment><description>&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;I found out about this blog a few days ago. Malcolm Smith,&amp;nbsp;a developer from the Transactional NTFS team is blogging at &lt;/FONT&gt;&lt;a href="http://blogs.msdn.com/because_we_can/"&gt;&lt;FONT face=Tahoma size=2&gt;http://blogs.msdn.com/because_we_can/&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=412486" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category></item><item><title>Using Windows XP SP2, Windows Server 2003 SP1 and MSDTC on Clusters</title><link>http://blogs.msdn.com/florinlazar/archive/2005/04/27/using-windows-xp-sp2-windows-server-2003-sp1-and-msdtc-on-clusters.aspx</link><pubDate>Wed, 27 Apr 2005 13:27:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:412482</guid><dc:creator>florinlazar</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/412482.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=412482</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=412482</wfw:comment><description>&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;In order to allow Windows XP SP2 or Windows Server 2003 SP1 to talk to a remote MSDTC located in a cluster, the security level for MSDTC needs to be set to "Incoming Caller Authentication Required". (see &lt;/FONT&gt;&lt;a href="http://blogs.msdn.com/florinlazar/archive/2004/06/18/159127.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://blogs.msdn.com/florinlazar/archive/2004/06/18/159127.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; for more details on MSDTC security levels).&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=412482" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/clusters/default.aspx">clusters</category></item><item><title>MSDN Product Feedback Center</title><link>http://blogs.msdn.com/florinlazar/archive/2005/04/21/410489.aspx</link><pubDate>Thu, 21 Apr 2005 22:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:410489</guid><dc:creator>florinlazar</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/florinlazar/comments/410489.aspx</comments><wfw:commentRss>http://blogs.msdn.com/florinlazar/commentrss.aspx?PostID=410489</wfw:commentRss><wfw:comment>http://blogs.msdn.com/florinlazar/rsscomments.aspx?PostID=410489</wfw:comment><description>&lt;P class=MsoPlainText&gt;&lt;FONT face=Tahoma size=2&gt;You've found a bug in a Microsoft product, and you don't know where to report it? Use MSDN Product Feedback Center &lt;/FONT&gt;&lt;A href="http://lab.msdn.microsoft.com/productfeedback/default.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;http://lab.msdn.microsoft.com/productfeedback/default.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; to submit it. You can collaborate with Microsoft developers, MVPs, and beta testers to identify problems and workarounds, and then track feedback online. You also get notifications of changes and fixes.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=410489" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/florinlazar/archive/tags/MSDTC/default.aspx">MSDTC</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Enterprise+Services/default.aspx">Enterprise Services</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Transactions/default.aspx">Transactions</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/COM_2B00_/default.aspx">COM+</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Microsoft+Windows/default.aspx">Microsoft Windows</category><category domain="http://blogs.msdn.com/florinlazar/archive/tags/Indigo/default.aspx">Indigo</category></item></channel></rss>