Problem
We have a component that is configured as transactional ("required"). It calls a stored procedure. SP is a compound procedure that calls several other stored procedures. Some of the called SPs can insert some data, but if certain conditions are not met, the whole transaction is supposed to be rolled back. This is achieved by marking a COM+ component as transactional and calling SetAbort:
In Activate:
HRESULT hr = m_spObjectContext->CreateInstance(__uuid
In the actual method:
if( hr == S_OK )
m_spObjectContext->SetComplete();
else
m_spObjectContext->SetAbort();
Suddenly it stopped working on some machines. Code executes fine, HRESULT is reported correctly, SetAbort returns S_OK. But database calls act like they are all committed! Impossible...
Resolution
After upgrading our machines to WinXP we experienced long delays in some database calls duration. We found a recommendation to disable OLE DB resource pooling services. For some reasons it was recommended to use value -4 in OLE DB Services flags:
"OLE DB Services = 0" No Services
"OLE DB Services = -1" All Services (default)
"OLE DB Services = -2" All Services Except Pooling
"OLE DB Services = -4" All Services Except Pooling and Auto-Enlistment
"OLE DB Services = -5" All Services Except Client Cursor
"OLE DB Services = -6" All Services Except Client Cursor and Pooling.
As you see, "OLE DB Services = -4" means disabling both resource pooling and auto-enlistment. This broke our COM+ transactional components. Using value "-2" helped.
Bottom line: do not disable transaction auto-enlistment for transactional COM+ component. Actually, quite obvious, should have thought about it.