# 8. Transactions

Probably you have already wondered how db4o handles concurrent access to a single database. Just as any other DBMS, db4o provides a transaction mechanism. Before we take a look at multiple, perhaps even remote, clients accessing a db4o instance in parallel, we will introduce db4o transaction concepts in isolation.

## 8.1. Commit and rollback

You may not have noticed it, but we have already been working with transactions from the first chapter on. By definition, you are always working inside a transaction when interacting with db4o. A transaction is implicitly started when you open a container, and the current transaction is implicitly committed when you close it again. So the following code snippet to store a car is semantically identical to the ones we have seen before; it just makes the commit explicit.

`[storeCarCommit] Dim pilot As Pilot = New Pilot("Rubens Barrichello", 99) Dim car As Car = New Car("BMW") car.Pilot = pilot db.[Set](car) db.Commit()`

`[listAllCars] Dim result As ObjectSet = db.[Get](GetType(Car)) ListResult(result)`

OUTPUT: 1 BMW[Rubens Barrichello/99]/0

However, we can also rollback the current transaction, resetting the state of our database to the last commit point.

`[storeCarRollback] Dim pilot As Pilot = New Pilot("Michael Schumacher", 100) Dim car As Car = New Car("Ferrari") car.Pilot = pilot db.[Set](car) db.Rollback()`

`[listAllCars] Dim result As ObjectSet = db.[Get](GetType(Car)) ListResult(result)`

OUTPUT: 1 BMW[Rubens Barrichello/99]/0

## 8.2. Refresh live objects

There's one problem, though: We can roll back our database, but this cannot automagically trigger a rollback for our live objects.

`[carSnapshotRollback] Dim result As ObjectSet = db.[Get](New Car("BMW")) Dim car As Car = DirectCast(result.[Next](), Car) car.Snapshot() db.[Set](car) db.Rollback() Console.WriteLine(car)`

OUTPUT: BMW[Rubens Barrichello/99]/3

We will have to explicitly refresh our live objects when we suspect they may have participated in a rollback transaction.

`[carSnapshotRollbackRefresh] Dim result As ObjectSet = db.[Get](New Car("BMW")) Dim car As Car = DirectCast(result.[Next](), Car) car.Snapshot() db.[Set](car) db.Rollback() db.Ext().Refresh(car, Integer.MaxValue) Console.WriteLine(car)`

OUTPUT: BMW[Rubens Barrichello/99]/0

What is this ExtObjectContainer construct good for? Well, it provides some functionality that is in itself stable, but the API may still be subject to change. As soon as we are confident that no more changes will occur, ext functionality will be transferred to the common ObjectContainer API. We will cover extended functionality in more detail in a later chapter.
Finally, we clean up again.

`[deleteAll] Dim result As ObjectSet = db.[Get](GetType(Object)) For Each item As Object In result db.Delete(item) Next`

## 8.3. Conclusion

We have seen how transactions work for a single client. In the next chapter we will see how the transaction concept extends to multiple clients, whether they are located within the same VM or on a remote machine.

## 8.4. Full source

`Imports System
Imports System.IO
Imports com.db4o
Namespace com.db4o.f1.chapter5
Public Class TransactionExample
Inherits Util
Public Shared Sub Main(ByVal args As String())
File.Delete(Util.YapFileName)
Dim db As ObjectContainer = Db4oFactory.OpenFile(Util.YapFileName)
Try
StoreCarCommit(db)
db.Close()
db = Db4oFactory.OpenFile(Util.YapFileName)
ListAllCars(db)
StoreCarRollback(db)
db.Close()
db = Db4oFactory.OpenFile(Util.YapFileName)
ListAllCars(db)
CarSnapshotRollback(db)
CarSnapshotRollbackRefresh(db)
Finally
db.Close()
End Try
End Sub
Public Shared Sub StoreCarCommit(ByVal db As ObjectContainer)
Dim pilot As Pilot = New Pilot("Rubens Barrichello", 99)
Dim car As Car = New Car("BMW")
car.Pilot = pilot
db.[Set](car)
db.Commit()
End Sub
Public Shared Sub ListAllCars(ByVal db As ObjectContainer)
Dim result As ObjectSet = db.[Get](GetType(Car))
ListResult(result)
End Sub
Public Shared Sub StoreCarRollback(ByVal db As ObjectContainer)
Dim pilot As Pilot = New Pilot("Michael Schumacher", 100)
Dim car As Car = New Car("Ferrari")
car.Pilot = pilot
db.[Set](car)
db.Rollback()
End Sub
Public Shared Sub CarSnapshotRollback(ByVal db As ObjectContainer)
Dim result As ObjectSet = db.[Get](New Car("BMW"))
Dim car As Car = DirectCast(result.[Next](), Car)
car.Snapshot()
db.[Set](car)
db.Rollback()
Console.WriteLine(car)
End Sub
Public Shared Sub CarSnapshotRollbackRefresh(ByVal db As ObjectContainer)
Dim result As ObjectSet = db.[Get](New Car("BMW"))
Dim car As Car = DirectCast(result.[Next](), Car)
car.Snapshot()
db.[Set](car)
db.Rollback()
db.Ext().Refresh(car, Integer.MaxValue)
Console.WriteLine(car)
End Sub
End Class
End Namespace
`

--
generated by Doctor courtesy of db4objects Inc.