I've googled a lot and repeatedly stumbled upon a few articles which make me feel - this ain't gonna work!
When you write managed code in a Script component, you cannot call the AcquireConnection method of connection managers that return unmanaged objects, such as the OLE DB connection manager and the Excel connection manager. However, you can read the ConnectionString property of these connection managers, and connect to the data source directly in your code by using the connection string of an OLEDB connection from the System.Data.OleDb namespace.
And I believe, if I cannot call Acquire Connection, then I cannot participate in the transaction which the component container has started in the SSIS package.
My existing SSIS packages use OLEDB Connection Managers (Native) and the same connection manager will be used by my custom component. At the moment, I'm using the connection string without calling Acquire Connection - in this approach since I'm creating a new connection, the component cannot participate in any transaction which the parent SSIS sequence container might have started, which in turn does not cause rollback of changes done by the custom component in case failures happen downstream. And changing the existing connection managers to ADO.NET doesnt look feasible due to huge impact since the existing OleDb connection managers are used in many OleDb components like OleDb destination in existing code.
Is there any way to work around this issue - so basically I want to get transactions to work using OleDb connection manager in a custom component?
Well, DbConnection and its derivative, SqlConnection class has method
EnlistTransaction
, which allows to add (enlist) this connection to a distributed transaction. Please note that is is a Distributed Transaction managed by MS DTC, not native MS SQL transaction.Theoretically (I have never done that in such specific scenario), you can open a managed connection based on the connection string you derived from OLE DB conn manager, and enlist it into a transaction. Things to look for and to check in the development:
TransactionSupport <> Required
), transaction parameter will benull
. You should handle this case in code as well.Transaction
parameter inAquireConnection
has typeobject
, the docs say that it is a handle to a distributed transaction. I would do a breakpoint right on enteringAquireConnection
method and check its real structure; you need to cast it toSystem.Transactions.Transaction
type.System.Transactions.Transaction.Current
. Perhaps, it might work.Please update on your results.