{"id":671,"date":"2009-10-01T22:30:54","date_gmt":"2009-10-01T21:30:54","guid":{"rendered":"http:\/\/www.gamlor.info\/wordpress\/?p=671"},"modified":"2021-03-11T09:44:58","modified_gmt":"2021-03-11T08:44:58","slug":"db4o-transactions","status":"publish","type":"post","link":"https:\/\/www.gamlor.info\/wordpress\/2009\/10\/db4o-transactions\/","title":{"rendered":"db4o: Transactions"},"content":{"rendered":"<p>So I showed <a href=\"?p=620\">the basics<\/a>, explained <a href=\"?p=637\">the activation-system<\/a> and pointed out how db4o manages <a href=\"?p=654\">object-identities<\/a>. So far so good, but I\u2019ve never explain a very important\u00a0feature of most databases, the transactions. Time to catch up.<\/p>\n<p>(All posts of this series: <a href=\"?p=620\">the basics<\/a>, <a href=\"?p=637\">activation<\/a>, <a href=\"?p=654\">object-identity<\/a>, <a href=\"?p=671\">transactions<\/a>, <a href=\"?p=695\">persistent classes<\/a>, <a href=\"?p=733\">single container concurrency<\/a>, <a href=\"?p=744\">Queries in Java, C# 2.0<\/a>, <a href=\"?p=779\">client-server concurrency<\/a>, <a href=\"?p=840\">transparent persistence<\/a>, <a href=\"?p=949\">adhoc query tools<\/a>)<\/p>\n<h3>Transactions<\/h3>\n<p>Actually we never used transaction so far, right? So it&#8217;s like auto commit? Lets try it out. First we run a little application which stores a object. After that the application goes into an endless loop. What do you do with application which hangs like this? Right, kill that bastard. So we kill our application with the Task-Manager or the Visual-Studio-Debugger.<\/p>\n<pre class=\"csharpcode\">File.Delete(<span class=\"str\">\"database.db4o\"<\/span>);\r\n<span class=\"kwrd\">using<\/span> (var db = StartDataBase())\r\n{\r\n    db.Store(<span class=\"kwrd\">new<\/span> SimpleObject(<span class=\"str\">\"A New Object\"<\/span>));\r\n    <span class=\"kwrd\">while<\/span> (<span class=\"kwrd\">true<\/span>)\r\n    {\r\n        Console.Out.WriteLine(<span class=\"str\">\"Demo: Kill this process now!! (Yay, Ctrl Alt Delete\"<\/span>);\r\n        Console.Read();\r\n    }\r\n}<\/pre>\n<p>So our demo-application was terminated abnormally. So let\u2019s check what is in our database.<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">using<\/span> (var db = StartDataBase())\r\n{\r\n    var objects = (from SimpleObject o <span class=\"kwrd\">in<\/span> db select o);\r\n    AssertEquals(1, objects.Count());\r\n}<\/pre>\n<p>Surprise, surprise, the test fails. Nothing is in the database. The reason is simple. Db4o automatically creates a transaction for you. As soon as you open the object-container a transaction is started. This transaction has the ACID-properties (<a href=\"http:\/\/en.wikipedia.org\/wiki\/ACID\">Wikipedia<\/a>, <a href=\"http:\/\/developer.db4o.com\/Documentation\/Reference\/db4o-7.12\/net35\/reference\/html\/reference\/basic_concepts\/acid_model.html\">db4o<\/a>) like other databases.<\/p>\n<div id=\"attachment_673\" style=\"width: 310px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4o-tx.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-673\" class=\"size-medium wp-image-673\" title=\"db4o-tx\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4o-tx-300x99.png\" alt=\"db4o transactions\" width=\"300\" height=\"99\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4o-tx-300x99.png 300w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4o-tx.png 1024w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-673\" class=\"wp-caption-text\">db4o transactions<\/p><\/div>\n<h3>Controlling The Transaction<\/h3>\n<p>Well it\u2019s wonderful that db4o creates the transaction by default. But it would be pretty useless if you cannot control it. Of course you can do that. The IObjectContainer interface has two methods for this: Commit()- and Rollback(). When you call those, the transaction is committed or rolled back and a new transaction is started immediately . For example:<\/p>\n<pre class=\"csharpcode\">File.Delete(<span class=\"str\">\"database.db4o\"<\/span>);\r\nvar db = StartDataBase();\r\n<span class=\"kwrd\">try<\/span>\r\n{\r\n    db.Store(<span class=\"kwrd\">new<\/span> SimpleObject(<span class=\"str\">\"Expect-To-Be-Committed\"<\/span>));\r\n    db.Commit();\r\n    db.Store(<span class=\"kwrd\">new<\/span> SimpleObject(<span class=\"str\">\"Expect-To-Be-Not-Committed\"<\/span>));\r\n    <span class=\"kwrd\">throw<\/span> <span class=\"kwrd\">new<\/span> SomethingWentWrongException();\r\n} <span class=\"kwrd\">catch<\/span>(SomethingWentWrongException)\r\n{\r\n    db.Rollback();\r\n} <span class=\"kwrd\">finally<\/span>\r\n{\r\n    db.Dispose();\r\n}\r\n<span class=\"kwrd\">using<\/span> (var checkDB = StartDataBase())\r\n{\r\n    var exists = (from SimpleObject o <span class=\"kwrd\">in<\/span> checkDB\r\n                  <span class=\"kwrd\">where<\/span> o.Content.Equals(<span class=\"str\">\"Expect-To-Be-Committed\"<\/span>)\r\n                  select o);\r\n    AssertEquals(1, exists.Count());\r\n    var wasNotCommited = (from SimpleObject o <span class=\"kwrd\">in<\/span> checkDB\r\n                          <span class=\"kwrd\">where<\/span> o.Content.Equals(<span class=\"str\">\"Expect-To-Be-Not-Committed\"<\/span>)\r\n                  select o);\r\n    AssertEquals(0, wasNotCommited.Count());\r\n}<\/pre>\n<p>So this works fine. By the way, the Close()- and Dispose()-methods call Commit() implicitly, so with the C# using-statement you commit automatically.<\/p>\n<p><a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4o-commit.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-674\" title=\"db4o-commit\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4o-commit.png\" alt=\"db4o-commit\" width=\"500\" height=\"452\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4o-commit.png 500w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4o-commit-300x271.png 300w\" sizes=\"(max-width: 500px) 100vw, 500px\" \/><\/a><\/p>\n<p><a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4o-rollback.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-672\" title=\"db4o-rollback\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4o-rollback.png\" alt=\"db4o-rollback\" width=\"600\" height=\"425\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4o-rollback.png 600w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4o-rollback-300x212.png 300w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/a><\/p>\n<p>Personally I use a wrapper around the transaction handling. It takes a closure which contains the db-operations and ensures that everything runs through or everything is rolled back:<\/p>\n<pre class=\"csharpcode\">dataBase.InTransaction(\r\n    tx=&gt;{\r\n        db.Store(<span class=\"kwrd\">new<\/span> DemoObject());\r\n    });<\/pre>\n<h3>Don\u2019t Let Your Objects Fall Behind<\/h3>\n<p>Now to a really nasty detail of the db4o-transaction-handling. We retrieve a object and change a property. Then we update this object in the database with Store(). After that we rollback the transaction. The demo-code:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">using<\/span>(var db = StartDataBase())\r\n{\r\n    var single = (from SimpleObject o <span class=\"kwrd\">in<\/span> db\r\n                  select o).Single();\r\n    single.Content = <span class=\"str\">\"New Value\"<\/span>;\r\n    db.Store(single);\r\n    db.Rollback();\r\n    AssertEquals(<span class=\"str\">\"Old-Value\"<\/span>, single.Content);\r\n}<\/pre>\n<p>Unfortunately this test will fail =(. When you rollback a transaction your <a href=\"http:\/\/developer.db4o.com\/Documentation\/Reference\/db4o-7.12\/net35\/reference\/html\/reference\/basic_concepts\/transaction.html#Refresh Live Objects\">objects in memory aren\u2019t rolled back automatically<\/a>. So you have to be very careful when try to resume after a some kind of error. So if you want to set a object in the state of database you can use Refresh():<\/p>\n<pre class=\"csharpcode\">db.Rollback();\r\ndb.Ext().Refresh(single,<span class=\"kwrd\">int<\/span>.MaxValue);<\/pre>\n<pre class=\"csharpcode\"><a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4-state.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-675\" title=\"db4-state\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4-state.png\" alt=\"db4-state\" width=\"600\" height=\"318\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4-state.png 600w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/db4-state-300x159.png 300w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/a><\/pre>\n<h3>Resume-Strategy<\/h3>\n<p>Now we know how we can commit and rollback a transaction. Also we know that when we rollback a transaction, the objects in memory keep their state. So when you want to resume after a rollback, you have to have some kind of strategy. This strategy heavily depends on your use case.<\/p>\n<h3>Isolation<\/h3>\n<p>In a client-server-model the isolation guarantees are important. Db4o has <a href=\"http:\/\/developer.db4o.com\/Documentation\/Reference\/db4o-7.12\/net35\/reference\/html\/reference\/basic_concepts\/acid_model\/isolation_level_for_db4o.html\">read-committed isolation properties<\/a>.\u00a0<\/p>\n<h3>Next time<\/h3>\n<p>So far I\u2019ve showed some basics of db4o. Of course this is only the tip of the iceberg. You can read up all the details in the <a href=\"http:\/\/developer.db4o.com\/Documentation.aspx\">documentation<\/a>. So next time I give some tips on how to model your persisted classes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>So I showed the basics, explained the activation-system and pointed out how db4o manages object-identities. So far so good, but I\u2019ve never explain a very important\u00a0feature of most databases, the&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[150],"tags":[21,100],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/671"}],"collection":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/comments?post=671"}],"version-history":[{"count":5,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/671\/revisions"}],"predecessor-version":[{"id":3835,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/671\/revisions\/3835"}],"wp:attachment":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/media?parent=671"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/categories?post=671"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/tags?post=671"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}