Exception when closing SqlClient connection in a distributed transaction

S

S?ren Mondrup

I am using distributed transactions without using COM+. My code works
with OracleClient and our home grown ODBC wrapper, but not with
SqlClient. I get a type cast exception when closing a SqlClient
Connection that participates in a distributed transaction:

Exception: System.Reflection.TargetInvocationException: Exception has
been thrown by the target of an invocation. --->
System.InvalidCastException: Specified cast is not valid.
at System.Data.SqlClient.ConnectionPool.PutConnectionManualEnlisted(SqlInternalConnection
con)
at System.Data.SqlClient.ConnectionPool.PutDeactivatedConnection(SqlInternalConnection
con)
at System.Data.SqlClient.SqlConnection.Close()

My code looks like this:

using( Transaction myTransactionWrapper =
Transaction.Create( "tx unit test", IsolationLevels.ReadCommitted,
TimeSpan.FromSeconds( 20 ) ) )
{
System.EnterpriseServices.ITransaction tx =
myTransactionWrapper.ClrTransaction;

using( SqlConnection con = new SqlConnection() )
{
con.ConnectionString = ConnectionString;
con.Open();
con.EnlistDistributedTransaction( tx );

using( SqlCommand cmd = new SqlCommand() )
{
cmd.Connection = con;
cmd.CommandText = "insert into TxTest values ( 0 )";
cmd.ExecuteNonQuery();
}

con.Close(); // throws exception
}

myTransactionWrapper.Commit();
}

The Transaction class wraps an unmanaged ITransaction.
I obtain the transaction through DtcGetTransactionManagerExProcAddr().
The unmanaged interface pointer is then marshalled to
System.EnterpriseServices.ITransaction with
Marshal.GetTypedObjectForIUnknown(). So I don't use COM+ in any way.

Does anyone know why SqlConnection.Close() throws an exception?

I understand that the connection is supposed to be put into a sub pool
because it participates in a distributed transaction. Could it be that
SqlClient expects a specific implementation of ITransaction, that also
handles this sub pool?

What should I do? Use the "secret" ITransaction implementation? Handle
the sub pool myself? Wait for Whitbey? Wait for Longhorn?


regards Søren Mondrup
 
S

S?ren Mondrup

I looked at SqlClient.ConnectionPool.PutConnectionManualEnlisted()
with Reflector. The ITransaction reference is cast to
UCOMIConnectionPoint, which is what throws the exception. The
unmanaged ITransaction doesn't support IConnectionPoint.

It seems like the COM+ runtime callable wrapper for ITransaction
implements UCOMIConnectionPoint. It would be really nice if could use
this implementation. I took a look at it. All I can se is that it is a
__ComObject. That isn't much to go on.

I think I'm nearing a dead end. Dropping SqlClient will be one of my
next steps :(


Søren Mondrup
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top