1. Home
  2. Computing & Technology
  3. Delphi Programming

Fixing the "Transaction ... an object is in a zombie state"
in ADO database applications

By , About.com Guide

When developing database applications using ADO (with OLE DB Provider for SQL Server) where transactions are involved you might be getting the horrible run-time "ITransaction::Comit or ITransaction::Abort was called, an object is in a zombie state" exception.

To fix the error, you need to add two dynamic properties to the underlying Recordset object: "Preserve on Commit" and "Preserve on Abort". More info on error can be found on MSDN

In Delphi, the best place to add those properties is the OnWillExecute event of the TADOConnection object:

~~~~~~~~~~~~~~~~~~~~~~~~~
procedure TDataModule.ADOConnWillExecute(Connection: TADOConnection;
   var CommandText: WideString; var CursorType: TCursorType;
   var LockType: TADOLockType; var CommandType: TCommandType;
   var ExecuteOptions: TExecuteOptions; var EventStatus: TEventStatus;
   const Command: _Command; const Recordset: _Recordset) ;
begin
   if RecordSet <> nil then
   begin
     Recordset.Properties['Preserve on commit'].Value := True;
     Recordset.Properties['Preserve on abort'].Value := True;
   end;
end;
~~~~~~~~~~~~~~~~~~~~~~~~~

An addition to this tip by Philippe Auphelle:
... I finally found the OnWillExecute of the TADOConnection that you mentionned, and sure it worked, but I didn't really like it: it looked like an overkill, as not every SQL execute on every dataset going through the connection requires this. And in my application, I have many, many datasets, and a single connection. So I wanted to find the right place to stuff it.

The solution came from Brian Bushay, on the Borland ADO forum, while I was looking for a way to use yet another RecordSet property, the "Update Criteria" one: Those recordset properties must be set in the BeforePost and BeforeDelete events. Those are the only places where the recordset is garanteed to be opened just before the Post (or Delete) that requires these Preserve properties. AfterOpen doesn't work properly, because the properties are reset by a Requery as well. And AfterCreateRecorset doesn't work because when it happens, the recordset is created, but not opened yet...

Some obscure paragraph in MSDN mentions this:
"Recordset Dynamic Properties
Note that the Dynamic Properties of the Recordset object go out of scope (become unavailable) when the Recordset is closed."

Delphi tips navigator:
» Raising TPageControl's OnChagning and OnChange events from code
« How to cancel the TDBNavigator button click

Explore Delphi Programming
About.com Special Features

Reader's Choice Award Winners

What are the best instant messengers, apps, editors and more? You told us, for our 2010 technology awards program. More >

iPad Central

Is Apple's new tablet computer impractical, a must-have -- or both? We'll help you figure it out. More >

  1. Home
  2. Computing & Technology
  3. Delphi Programming
  4. Coding Delphi Applications
  5. Delphi Tips and Tricks
  6. 2005 Delphi Tips
  7. Fixing the "Transaction ... an object is in a zombie state" error in Delphi ADO database applications

©2010 About.com, a part of The New York Times Company.

All rights reserved.