﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Ayende @ Rahien</title><link>http://ayende.com</link><description>Ayende @ Rahien</description><copyright>Copyright (C) Ayende Rahien  2004 - 2021 (c) 2026</copyright><ttl>60</ttl><item><title>Marc Selis commented on Who stole my transaction?</title><description>I'm having the same problem over here.  The problem is indeed that the Dispose causes the Commits to be executed on a background thread, and returns immediately.
  
  
For me this is a big problem, because after the commit my application (which is a console application) exits, and some of the commits are never executed.
  
  
To make things worse: there is no way of knowing when the commits are done.  Even the Transaction.TransactionCompleted event is fired before all commits have executed.
  
  
The only solution I have found so far is to either do a Thread.Sleep for a certain time, or to build in the loop below to check if some worker threads are still busy.
  
  
If you have found a better solution, I would be glad to know...
  
  
int workerThreads = 0;
  
int completionPortThreads = 0;
  
int maxWorkerThreads;
  
int maxCompletionPortThreads;
  
ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxCompletionPortThreads);
  
while(workerThreads!=maxWorkerThreads || completionPortThreads!=maxCompletionPortThreads)
  
{
  
	Thread.Sleep(10);
  
	ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
  
}
  
  
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment17</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment17</guid><pubDate>Sun, 18 Jul 2010 10:36:38 GMT</pubDate></item><item><title>Rik Hemsley commented on Who stole my transaction?</title><description>This is very worrying. What's the point of transactions where you can't be sure if they've been committed or not?
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment16</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment16</guid><pubDate>Tue, 01 Jun 2010 15:50:38 GMT</pubDate></item><item><title>Ayende Rahien commented on Who stole my transaction?</title><description>Frank,
  
With Volatile, you don't actually get DTC
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment15</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment15</guid><pubDate>Sun, 30 May 2010 11:04:28 GMT</pubDate></item><item><title>Frank Quednau commented on Who stole my transaction?</title><description>EnlistVolatile works as you expect but the stack trace looks very different - don't know enough about all this business to see where the exact differences are. All in all it is an amazing find indeed. Looks like the EnlistmentNotification implementations out there don't really commit in the Commit implementation of the EnlistmentNotification instance, as this apparently would be a pretty bad place to do so.
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment14</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment14</guid><pubDate>Sun, 30 May 2010 09:38:36 GMT</pubDate></item><item><title>Ayende Rahien commented on Who stole my transaction?</title><description>John,
  
There is no IDbTransaction used anywhere here.
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment13</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment13</guid><pubDate>Sun, 30 May 2010 06:29:30 GMT</pubDate></item><item><title>John Davidson commented on Who stole my transaction?</title><description>The documentation For IDBTransaction says thatit is for use with relational databases. It should probably read that it is for use with a database that implements locking strategies.
  
  
Given that RavenDB does not use locks, but rather MVCC, would it be possible to create your own non-IDBTransaction implementation so that MSDTC would not be utilized?
  
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment12</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment12</guid><pubDate>Sun, 30 May 2010 00:46:08 GMT</pubDate></item><item><title>Ayende Rahien commented on Who stole my transaction?</title><description>Greg,
  
The problem isn't with the async, the problem is that Dispose returns before the transaction is actually committed.
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment11</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment11</guid><pubDate>Sat, 29 May 2010 20:50:00 GMT</pubDate></item><item><title>Ayende Rahien commented on Who stole my transaction?</title><description>Sasha,
  
That is a _big_ problem, what happen if you don't rely on locks for transactions?
  
Case in point, and how we got this error, is a case where we work in a lock free transactional system (MVCC).
  
If you read immediately after the transaction, you don't get locked, you get the _committed version_, which isn't what you just finished committing.
  
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment10</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment10</guid><pubDate>Sat, 29 May 2010 20:49:19 GMT</pubDate></item><item><title>Greg Law commented on Who stole my transaction?</title><description>If you enable tracing on System.Transactions, you'll see that the transactions are committing and disposing when the using block goes out of scope, but the notification callback sometimes happens after the TransactionScope constructors are called on the next iteration.
  
  
This leads me to believe that it's probably using an AsyncCallback
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment9</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment9</guid><pubDate>Sat, 29 May 2010 18:38:04 GMT</pubDate></item><item><title>Sasha Goldshtein commented on Who stole my transaction?</title><description>Both Prepare() and Commit() execute on a thread different from the main thread, that executes TransactionScope.Dispose(). The documentation is accurate in that you will not observe the Dispose() method returning before the Prepare() method has been synchronously called and the DTC decided to commit the transaction.
  
  
However, my understanding of the documentation (and the actual implementation) is that the Commit() method is called after the transaction outcome has been decided, and all the parties involved have no way of effecting any changes to the transaction.
  
  
If everyone properly uses transactions or at least locks everything properly, there shouldn't be any visible problem as a result of this. For example, say that after the end of the tx scope you start another transaction that relies on the changes committed by the first transaction. The first transaction would not have released its locks before the Commit() method returned, so the second transaction will wait for these locks if it relies on the same data.
  
  
In other words, how is this such a big problem? 
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment8</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment8</guid><pubDate>Sat, 29 May 2010 16:06:43 GMT</pubDate></item><item><title>Omer Mor commented on Who stole my transaction?</title><description>Sorry - my failure to get Rollback called was a bug on my side.
  
But your observation still stands.
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment7</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment7</guid><pubDate>Sat, 29 May 2010 15:52:15 GMT</pubDate></item><item><title>Omer Mor commented on Who stole my transaction?</title><description>Weird. It appears that you're right.
  
I also failed to get Rollback being called after forcing rollback from the prepare method by calling preparingEnlistment.ForceRollback().
  
I hope some from the framework team would answer this.
  
Have you filed a Connect bug on this? (I know you don't believe in Connect, but still).
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment6</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment6</guid><pubDate>Sat, 29 May 2010 15:43:25 GMT</pubDate></item><item><title>James commented on Who stole my transaction?</title><description>Do you still get the error if you use call the TransactionScope constructor with TransactionScopeOption.RequiresNew?
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment5</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment5</guid><pubDate>Sat, 29 May 2010 14:31:27 GMT</pubDate></item><item><title>Ayende Rahien commented on Who stole my transaction?</title><description>Steve,
  
Yes
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment4</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment4</guid><pubDate>Sat, 29 May 2010 13:46:09 GMT</pubDate></item><item><title>Steve Degosserie commented on Who stole my transaction?</title><description>Is it a distributed transaction (therefore managed by MSDTC) ?
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment3</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment3</guid><pubDate>Sat, 29 May 2010 12:10:26 GMT</pubDate></item><item><title>Ayende Rahien commented on Who stole my transaction?</title><description>Release &amp; Debug
  
With &amp; without debugger.
  
Inlining doesn't matter
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment2</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment2</guid><pubDate>Sat, 29 May 2010 11:13:00 GMT</pubDate></item><item><title>John commented on Who stole my transaction?</title><description>Debug or Release build? Running under debugger? Perhaps disable inlining?
</description><link>http://ayende.com/4528/who-stole-my-transaction#comment1</link><guid>http://ayende.com/4528/who-stole-my-transaction#comment1</guid><pubDate>Sat, 29 May 2010 10:37:32 GMT</pubDate></item></channel></rss>