Hi guys,
I am designing the transaction API of a framework that will allow .NET code to
run inside a
database server. For the ease of use, we do not want users to care about
transaction
management manually. There will be implicit transaction management much like
what we
can already do with System.Transactions.TransactionScope, but declaratively
(using a
custom attribute -- and PostSharp under the hood, of course ;- ). The aim is to
make it very, very easy to code applications running directly in the database
server.
I am in front of a dilemna and would like to hear your opinion about that.
Since transactions run in optimistic concurrency mode, there can be conflicts
during
commit. Of course the whole transaction fails in that case -- this is not the
problem.
The most common solution to a conflict is to restart the whole transaction.
Since
transactions are defined declaratively, the server is in charge, and we can
execute again
the block that actually opened the transaction.
Of course, restarting a transaction is safe *only* the sole effects of the code
are either
transactional (can be rolled back), either idempotent (can be repeated).
We have currently no way to analyze the code to determine its effect.
Now, what's the best behavior?
1. Transactions are automatically restarted by default unless some block vote
against it (in
this case the conflict is not solved and the entire transaction failed).
2. Transaction are restarted only on demand, when a block asks it. But this
works only
when that block is actually a transaction boundary, i.e. it opened a new
transaction. So it
is quite limited. Another problem is that, if we make it on-demand, I expect
most of
programmers to forget to demand it. Conversely, I assume non-transactional code
(like
I/O) will be coded by more senior developers, so they won't forget to vote
against
automatic retrial.
Opinions welcome ;)
Gael - postsharp.org