Click here to Skip to main content
15,888,579 members
Articles / Programming Languages / C#

Nested Transactions for System.Data.SQLite with Savepoints

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
10 Sep 2016CPOL3 min read 14.9K   397   2   3
A set of extension methods giving System.Data.SQLite access to Savepoints

Introduction

SQLite does not inherently allow nested transactions. However, it does allow for a transaction to be marked with intermediate savepoints, which emulate nested transactions to a degree. The documentation explaining how all this works can be found here^.

Background

Although SAVEPOINT commands can be issued directly on a database connection without a current transaction, doing so implicitly creates a transaction and alters the way the RELEASE command works. In order to alleviate any confusion, the module is set up so that Savepoints can only be created within the context of a transaction. The resulting updates to the database are therefore only written when a COMMIT is issued, and the entire transaction is aborted if a ROLLBACK is issued, regardless of any Releases or Rollbacks of Savepoints within the transaction. This is consistent with the way transactions work in general (with or without Savepoints).

Using the Code

All of the code required is in a single .cs file. Rather than putting it into a class library, just include the file into your projects and start using it (although you may build it into a separate library if you so desire). In fact, the code all exists in a single static extension class. There are no special objects as far as usage of the extension is concerned.

Most of the manipulation of Savepoints is handled in extension methods on the SQLiteTransaction object. There are four extension methods defined for the SQLiteTransaction object. There are also two BeginTransaction extension methods for the SQLiteConnection object, that take an additional string savepointName parameter, and automatically add the named Savepoint to the newly created Transaction.

It is important to note that all Savepoint names are case-insensitive, and do not have to be unique. Any Release or Rollback of a Savepoint will act upon the most recent one with a matching name.

The four extension methods defined for the SQLiteTransaction object are:

  • void AddSavepoint(string savepointName)

    This method, as its name suggests, creates a new Savepoint within the Transaction.

  • void ReleaseSavepoint(string savepointName)

    I think the best description of how this works is the 2nd definition in the SQLite documentation:

    Another view of RELEASE is that it merges a named transaction into its parent transaction, so that the named transaction and its parent become the same transaction. After RELEASE, the named transaction and its parent will commit or rollback together, whatever their fate may be.

    This means that all commands within the Savepoint that have not been previously rolled back are effectively appended to the commands immediately preceding the Savepoint, and the released Savepoint no longer exists in the transaction. Any Savepoints following the one being released, that have not been previously been released or rolled back, are also automatically released at this time.

  • void RollbackToSavepoint(string savepointName)

    This method rolls back all commands issued following the named Savepoint, even if those commands include Savepoints that have previously been Released. The named Savepoint itself, however, still exists. Any commands issued to the transaction after the Rollback are still considered to be a part of that Savepoint.

  • void RollbackAndRelease(string savepointName)

    This command encapsulates both a Rollback and a Release, issued in succession. When issued like this, the transaction is returned to the state it was in immediately before the named Savepoint was created.

Points of Interest

Performing a SQLiteTransaction.Commit(), SQLiteTransaction.Rollback(), or closing or disposing the underlying connection, automatically releases the list of Savepoints from the transaction. This is internally managed by attaching event handlers on the connection's Commit, Rollback, StateChange, and Disposed events. I did find out the hard way, however, that it was important to remove these event handlers from the list when disposing of the list. Because the events were attached to connection object, a new transaction created on that connection was firing the events within deleted lists.

I also learnt that Stack enumerators go from last to first item (i.e. the order the items will be removed, and not the order in which they were entered).

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Australia Australia
Been programming for 40 years now, starting when I was 13 on DEC PDP 11 (back in the day of paper tape storage, and hex switch boot procedures). Got right into micro-computers from an early age, with machines like the Dick Smith Sorcerer and the CompuColor II. Started CP/M and MS-DOS programming in the mid 1980's. By the end of the '80's, I was just starting to get a good grip on OOP (Had Zortech C++ V1.0).

Got into ATL and COM programming early 2002. As a result, my gutter vocabulary has expanded, but it certainly keeps me off the streets.

Recently, I have had to stop working full time as a programmer due to permanent brain damage as a result of a tumour (I just can't keep up the pace required to meet KPI's). I still like to keep my hand in it, though, and will probably post more articles here as I discover various tricky things.

Comments and Discussions

 
Questionhave you consider to post this as a tip? Pin
Nelek11-Sep-16 0:54
protectorNelek11-Sep-16 0:54 
GeneralRe: have you consider to post this as a tip? Pin
Midi_Mick11-Sep-16 1:38
professionalMidi_Mick11-Sep-16 1:38 
GeneralRe: have you consider to post this as a tip? Pin
Nelek11-Sep-16 8:17
protectorNelek11-Sep-16 8:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.