There is an important difference between transactions started in Transact-SQL stored procedures and those started in managed code: common language runtime (CLR) code cannot unbalance the transaction state on entry or exit of a CLR invocation. Be aware of the following implications of this difference:
A transaction started inside a CLR frame must be committed or rolled back, or else SQL Server generates an error when the frame is exited.
An outer transaction cannot be committed or rolled back inside the CLR code.
An attempt to commit a transaction not started in the same procedure causes a run-time error.
An attempt to roll back a transaction not started in the same procedure causes the transaction to hang (preventing any other side-effecting operation from happening). The transaction discontinues until the CLR code goes out of scope. Note that this can be useful when you detect an error inside your procedure and want to make sure the whole transaction terminates.