Transaction/Closure/Object - what's the difference? ''Is rollback an intrinsic property of objects?'' What's the difference between rolling back a transaction and destroying an object? ---- Transaction scope and object lifetime are orthogonal issues, not directly related to each other: While performing a UnitOfWork, I may create and discard many individual objects. ''(Particularly true if the objects are fine-grained, like integer, string, and point.)'' On the other hand, a transaction may involve calling only one method on an object, changing only a small part of its state. The ideal relationship between objects and transactions would be that rolling back a transaction would cause all objects involved in that transaction to revert back to their previous state. This is probably only achieved with some OO databases and particularly sophisticated OO to relational mapping products. ''(I suspect that this issue is one of the main reasons for Microsoft's strange object lifetime rules in MicrosoftTransactionServer.)'' You can create objects, like AcidCommand, that directly represent transaction semantics (or database resources). But such objects are the exception rather than the rule. -- JeffGrigg ---- * Closure - a closure is a function that captures the lexical environment in which it was created. GuySteele and GeraldSussman in the 1970s discovered the EquivalenceOfClosuresAndObjects through their invention of the SchemeLanguage. * Object - a set of functions that share a common environment. See ''closure'' above. * Transaction - usually this means some kind of unit of work that guarantees some properties about the changes, i.e. the AcidProperties [AtomicConsistentIsolatedDurable]. The unit of work could be defined as a Command object (i.e. the CommandPattern / [AcidCommand]) or it could be a function (i.e. a closure). For example the ErlangLanguage includes the MnesiaDatabase. Transactions are executed against this database by defining closures and handing a closure to the mnesia:transaction/1 function. raise(Employee_number, Raise) -> Closure = fun() -> [Employee] = mnesia:read({employee, Employee_number}), Salary = Employee#employee.salary + Raise, Updated_employee = Employee#employee{salary = Salary}, mnesia:write(Updated_employee) end, mnesia:transaction(Closure). The "raise" function will give an employee, identified by the Employee_number, a raise in the amount of Raise. To do this, it defines a function, bound to the variable "Closure", and asks the mnesia database to execute that function as a transaction (i.e. all the database changes succeed or all fail, etc.) The function will read the current employee data from the database, update its salary, and write the updated employee data to the database. -- PatrickLogan ----- Offhand, it looks to me that closures in this instance are an implementation detail of the MnesiaDatabase interface: I would guess that mnesia:transaction() puts some kind of marker in the closure it's given. mnesia:read() and mnesia:write() pick up this marker to join the transaction. -- JeffGrigg ''It's not that magical. The closure is just a regular Erlang closure. The mnesia:transaction function creates a new transaction in a concurrent mnesia process (an Erlang process is a lightweight thread). Then the closure is executed. Each mnesia call will execute in that mnesia process that has an active transaction. Then the mnesia:transaction function commits the transaction in that mnesia process. A concurrent transaction can be executed from another Erlang process. It is not necessary to pass a connection argument to the mnesia:transaction function. A concurrent transaction works with its own mnesia process. The process '''is''' the connection. Erlang is efficient enough to execute tens of thousands of concurrent processes. They are very lightweight. --PatrickLogan'' A similar concept in the OO world could look like this: 1. You make a class that inherits from the database's "Transaction" class. 2. You pass an instance of that class to the database's "perform a transaction" function. 3. The database starts a transaction, calls the "Perform Work" function on your class (You overrode the base class' definition), and then commits the work. Am I anywhere close? -- JeffGrigg ''That's it, Jeff. It shows the correspondence between a closure and an object relative to a transaction. --PatrickLogan'' ---- CategoryClosure