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

Holiday Central

What to eat, where to go, fun things to do and how to save money on the perfect gifts. More >

Family Tech Center

Stay connected and entertained with reviews on tips on the latest HDTVs, cellphones and more. 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

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

All rights reserved.