BloggingAbout.NET
Thoughts of developers
Native Objects Database
Robert Jan van Holland

Syndication

News

  • Hey! It's me!


    <!-- Begin Nedstat Basic code --> <!-- Title: Robert Jan van Holland --> <!-- URL: http://bloggingabout.net/rj/ --> <script language="JavaScript" type="text/javascript" src="http://m1.nedstatbasic.net/basic.js"> </script> <script language="JavaScript" type="text/javascript" > <!-- nedstatbasic("ADQEqQkgn3Dw8t7jLnYe0vJBScRw", 0); // --> </script> <noscript>
    Gratis teller </noscript> <!-- End Nedstat Basic code --> <iframe src="http://bloggie.vanholland.net/Statistics.aspx" width="130" height="40" frameborder=0 scrolling="no" name="content"></iframe> Download Bloggie here! Installation & Configuration!

Yesterday I was browsing on the net searching for some solutions for challenges I currently have to cope with while working on my hobby projects; for example Bloggie. I wanted a simple storage mechanism where no client/server model is necessary. I preferred something for storing my objects so that no mapping to whataver relational model is needed.
So I came accross this website :
http://www.db4o.com/about/productinformation/

They have implemented a native object database mechanism that really caught my attention. I think it is really very cool to just store your objects in some way without the need of conterting / mapping it to some flat relational database model.
So I downloaded it and wrote a little test to see it work (see below).
How it works behind the scenes? I dont know... Performance? I dont know either...

But it does support query by example, cascading updates/deletes, transactions and a client/server model.
I dont think any reporting service will interact with this technique yet, so that is a drawback; but I see some really positive possibilities for standalone applications and small n-tier apps.

I think I'll dig in this product some more...
But i'm really curious what you guys think of this product? what drawbacks do you see? Let me know...

Addition :
The developers have a weblog at
http://www.people4objects.org/
A nice quote from this blog :
"This has nothing to do with scripting, but I stumbled across this very interesting OO database recently. db4objects a GNU licensed object database that has native Java and .Net interfaces. You can basically give it any object and it will store it for you with a single line of code. You can do pretty complex queries to get data out of it. Essentially, it returns lists of objects based on filters on the pool of objects it has stored. You can filter on class, any field value, and so sorting and that sort of thing. It has both internal and server-based modes, and I imagine it could be made transactional with any of the framework-based transaction engines. With a little rethinking of the persistence layer, this could save a lot of coding time in Java/.Net programs - no more database schema management, no more SQL insert, update, and delete statements."

To run this example... Download the package from their website... start a new c# windows app and add a reference to the downloaded dll “db4o.dll”.
Make sure you have a c:\temp directory because there your db container will be written to, or change the file path.
Copy paste this source first to wordpad and then in your form1.cs and run the app.

 

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using com.db4o;
using com.db4o.query;
 
namespace db4otest
{
    /// 
    /// Summary description for Form1.
    /// 
    public class Form1 : System.Windows.Forms.Form
    {
        /// 
        /// Required designer variable.
        /// 
        private System.ComponentModel.Container components = null;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Button button2;
        private System.Windows.Forms.Button button3;
        private System.Windows.Forms.Button button4;
        private System.Windows.Forms.Button button5;
 
        string filepath = @"c:\temp\db4o.db";
 
        public Form1()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();
 
            //
            // TODO: Add any constructor code after InitializeComponent call
            //
        }
 
        /// 
        /// Clean up any resources being used.
        /// 
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }
 
        #region Windows Form Designer generated code
        /// 
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// 
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.button2 = new System.Windows.Forms.Button();
            this.button3 = new System.Windows.Forms.Button();
            this.button4 = new System.Windows.Forms.Button();
            this.button5 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(24, 16);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(104, 23);
            this.button1.TabIndex = 0;
            this.button1.Text = "AddRJ";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // button2
            // 
            this.button2.Location = new System.Drawing.Point(24, 64);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(104, 23);
            this.button2.TabIndex = 1;
            this.button2.Text = "ShowNumber";
            this.button2.Click += new System.EventHandler(this.button2_Click);
            // 
            // button3
            // 
            this.button3.Location = new System.Drawing.Point(24, 88);
            this.button3.Name = "button3";
            this.button3.Size = new System.Drawing.Size(104, 23);
            this.button3.TabIndex = 2;
            this.button3.Text = "QueryForRJ";
            this.button3.Click += new System.EventHandler(this.button3_Click);
            // 
            // button4
            // 
            this.button4.Location = new System.Drawing.Point(24, 112);
            this.button4.Name = "button4";
            this.button4.Size = new System.Drawing.Size(104, 23);
            this.button4.TabIndex = 3;
            this.button4.Text = "Clear DB";
            this.button4.Click += new System.EventHandler(this.button4_Click);
            // 
            // button5
            // 
            this.button5.Location = new System.Drawing.Point(24, 40);
            this.button5.Name = "button5";
            this.button5.Size = new System.Drawing.Size(104, 23);
            this.button5.TabIndex = 4;
            this.button5.Text = "AddDennis";
            this.button5.Click += new System.EventHandler(this.button5_Click);
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(144, 149);
            this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                          this.button5,
                                                                          this.button4,
                                                                          this.button3,
                                                                          this.button2,
                                                                          this.button1});
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
 
        }
        #endregion
 
        /// 
        /// The main entry point for the application.
        /// 
        [STAThread]
        static void Main() 
        {
            Application.Run(new Form1());
        }
 
        private void button1_Click(object sender, System.EventArgs e)
        {
            ObjectContainer db = Db4o.openFile(filepath);
            try
            {
                Account a = new Account("RJ","rj@rj.net",@"http://vanholland.net");
                db.set(a);
                
            }
            finally
            {
                db.close();
            }
        }
 
        private void button2_Click(object sender, System.EventArgs e)
        {
            ObjectContainer db = Db4o.openFile(filepath);
            try
            {
                Account proto = new Account(null,null,null);
                ObjectSet result = db.get(proto);
                MessageBox.Show(result.size().ToString());
                
            }
            finally
            {
                db.close();
            }
        }
 
        private void button4_Click(object sender, System.EventArgs e)
        {
            ObjectContainer db = Db4o.openFile(filepath);
            ObjectSet result = db.get(new Account(null, null,null));
            while (result.hasNext())
            {
                db.delete(result.next());
            }
            db.close();
        }
 
        private void button3_Click(object sender, System.EventArgs e)
        {
            ObjectContainer db = Db4o.openFile(filepath);
            Query query = db.query();
            query.constrain(typeof(Account));
            query.descend("_name").constrain("RJ");
            ObjectSet result = query.execute();
            for (int i =0; i
            {
                if (result.hasNext())
                {
                    Account a = (Account)result.next();
                    
                    MessageBox.Show(a.Name);
                }
                else
                {
                    break;
                }
 
            }
            db.close();
        }
 
        private void button5_Click(object sender, System.EventArgs e)
        {
            ObjectContainer db = Db4o.openFile(filepath);
            try
            {
                Account a = new Account("Dennis","Dennis@dennis.com",@"http://dennis.net");
                db.set(a);
                
            }
            finally
            {
                db.close();
            }
        }
    }
 
    public class Account
    {
        string _name;
        string _emailadres;
        string _url;
 
        public Account(string name, string emailadres, string url)
        {
            _name = name;
            _emailadres = emailadres;
            _url = url;
        }
 
        public string Name
        {
            get
            {
                return _name;
            }
        }
 
        public string EmailAdres
        {
            get
            {
                return _emailadres;
            }
        }
 
        public string URL
        {
            get
            {
                return _url;
            }
        }
    }
}
 

Posted 03-01-2005 10:28 AM by Robert Jan van Holland
Filed under: ,

Comments

Robert Jan van Holland wrote re: Native Objects Database
on 03-01-2005 11:09 AM
AWESOME!!!

There's my reaction, satisfied now?! ;)

But seriously, I think it's great. Only drawbacks are that it's no proven technology, not to us and not to our customers. So you go start convincing our customers we should use this product. Second, no support. They can tell you that they will help and send email, but there's no commercial customer-supplier relationship. So when they're off on holiday, you're screwed! :)

But if they do have customers that are very happy about the product and these customers have implementated it into a large product, then I'd say we can try this db4o in a smaller project. Maybe worth a try. :)
Robert Jan van Holland wrote re: Native Objects Database
on 03-01-2005 11:47 AM
Interesting, but it makes me start wondering how they go about storing object trees. I couldn't find that in your post and on their site either (didn't look very closely though).

You don't want it to store it all referenced objects. A Connection object is useless when restored after 3 days because the connection is gone (I know, no more connections with this tool but in reality we still have databases).

But you do want to store some parts of the tree. Your Account might reference an Address object. The reference should be restored when restoring the Account object, because if it isn't your Account object has changed.

Any clues to this?
Robert Jan van Holland wrote re: Native Objects Database
on 03-01-2005 12:08 PM
My opinion is that I don't really like it...

Why: it doesn't support any kind of sql.
I would rather just use RDBMS with SQL support then wrap a OR layer around it...

Why:
No need to learn anything different.
No vendor lock in
The complex needs are satisfied.


Robert Jan van Holland wrote re: Native Objects Database
on 03-01-2005 1:13 PM
Off course I am no expert on this field yet :), but I really encourage you to download the package and read the tutorial included. How db4o handles inheritance, recursive objects and deep graphs (trees) is explained over there.

To give away a hint : it does store the referred classes and really nice is that it does not matter whether they are subclass members or direct instances. In fact it does not matter where they are situated in the inheritance tree at all. Really, download it and read chapter 6 and 7 of the tutorial....

I'm still trying to get a grip of this db4o... cant understand all of it yet.. but i will :)
Robert Jan van Holland wrote re: Native Objects Database
on 03-01-2005 4:25 PM
I'll try to answer your question Carlo.. hopefully it makes sense

Think of a class Body... which has a class Head, which a class Eye.
So, it will look like

Body -> Head -> Eye

In db4o the following is the same :
-----------------------------
Eye e = new Eye("Blue");
Head h = new Head("BIG");
Body b = new Body("Large");
h.eye = e;
b.head = h;
db.set(b); //db is our db4o container!

-----------------------------
Eye e = new Eye("Blue");
db.set(e);
Head h = new Head("BIG");
db.set(h);
Body b = new Body("Large");
db.set(b);
h.eye = e;
db.set(h);
b.head = h;
db.set(b);

in both cases db4o will save the objects with its references in the same way. The only thing i conclude from this is that db4o will save your objects and will take care of its references and so will restore the complete hierarchy when retrieving it again.

As I mentioned before, a beautiful thing hereby is that retrieving an object of whatever type, whereever in the object tree can be done by simply creating a prototype object of the type and execute a db.get(prototype).
So retrieving the eye would now be :

Eye eye = new Eye("Blue");
db.get(eye);
This will retrieve all blue eyes.. in our case just one...

If you just want to retrieve all eyes, execute :
Eye eye = new Eye(null);
db.get(eye);


To react to your Connection object example.. I dont think I will ever put a connection object as a member in a class.
I rather would use a string member with the connectionstring in some method wich will open the connection, perform some action
and then close and dispose it again.
Robert Jan van Holland wrote re: Native Objects Database
on 03-02-2005 9:58 AM
This kind of technology is very promising! It would save us a lot of development time, storing objects directly in a database.
I would love to do a project with this kind of technology...!!

But without a proper tool like SQL Enterprise Manager this product has no change. Every developer wants to be able to take a look in the database and browse through the data, or in this case, the objects.

There is another promising OO database for .NET, Matisse (http://www.matisse.com), which also has some tooling.
Eventhough it's not free, it might still be interesting for you.
And there's also a 3-part tutorial on www.codeproject.com for this one: http://www.codeproject.com/dotnet/introtomatisse_part1.asp

Have fun!
Robert Jan van Holland wrote re: Native Objects Database
on 03-03-2005 9:00 AM
So, after looking into db4o more extensively I'm getting a pretty good picture of what you can do with db4o.

My initial enthusiasm, I must admit, is replaced with the more realistic: "nice, not thrilling, but nice".

Although it's quite nice to store objects without any hassle, it stops there.
When you take db4o a bit further, you'll begin to miss some important stuff.

Small example:
Suppose i have 1.499 customer objects, all with a customerID, numbered consecutively.
If I want to add a new customer and want to see what the new customerID should be, I have to retrieve and instantiate all 1.499 customer objects to see what the highest customerID so far is.

Of course, there are alternatives to this problem, but I'm just illustrating the lack of SQL. You'd really need a "select max()..." here.

It just shows that, although db4o is very nicely done, db4o is not ready for enterprise purposes.
And I think their website confirms this, because most of their customers use db4o for small or embedded applications.
Robert Jan van Holland wrote re: Native Objects Database
on 03-04-2005 10:09 AM
I don't agree with you Ernst.
I think you should change your mind set about this. A customerid is something typical for a rdbms. You want some technical key for a record so other data dan be linked to it, and so the rdbms can perform optimalisation on that data, and so that referational integrity is implemented.

Why should we have a technical key in an oodbms?

If you create a Person class in .NET, do you add an "ID" field to it to make some instance unique? Dont't think so. By definition an object is unique. Other data is linked to an object it by using classes as members. But, as you can read below, internally a unique key is used, which off couse you can use also :

ObjectInfo info = ExtObjectContainer.getObjectInfo(Object)
UUID id = info.getUUID()


And you're right, db40 doesn't support SQL.. makes sense off course because SQL is based on tables and attributes!
What db4o does support is S.O.D.A. (=Simpe Object Data Access) (http://sourceforge.net/projects/sodaquery).
Please also read what the MONO project has to say about it : http://www.mono-project.com/DB4O

Also bear into mind (from knowledge base):
----------------------------
Size of database files
In the default setting, the maximum database file size is 2GB.
------------------------------
Identity fields
db4o assigns this internal ID to every object that is stored.
These IDs are guaranteed to be unique within one database file and they will stay the same in each ObjectContainer/ObjectServer session that is started with the same database file.

A tip : register at the site http://www.db4o.com/community/ontheroad/solutionlibrary/ and read the articles in the knowledge base

To conclude, I do think this is something really intersting, BUT indeed because it is new, you have to let go your old rdbms assumptions... and that is sometimes hard :)

Robert Jan van Holland wrote re: Native Objects Database
on 03-04-2005 11:26 AM
RJ,

Maybe you're right and I need to free my mind of the typical assumptions I have with relational databases.
But it makes me very curious how simple issues in a relational databases should be solved in an OODB...

I definitely will be looking into db4o some more because I really think this is cool technology!
I'm just a bit doubtfull that this is suitable for enterprise size apps.

But maybe someone from db4o can correct me if I'm wrong :)
Robert Jan van Holland wrote re: Native Objects Database
on 03-04-2005 3:19 PM
Hi all,

thank you RJ, for sending me a notice about this discussion and thank you very much for speaking so nicely about our product. I will try to answer the points that came up in the comments, in chronological order:

(1) We do have customers that like our product very much:
http://www.db4o.com/about/customers/">http://www.db4o.com/about/customers/

(2) We offer professional support, with guaranteed 24h response times. 10 hours of support are included in our db4o developer network membership (dDN) package. We believe that good support is one of our key assets and we have a very professional setup, to guarantee it, using a salesforce.com portal where you can enter and track your support cases as a dDN member.
Furthermore I think our free support in our newsgroup has a very high quality:
news://news.db4odev.com/db4o.users (NNTP newsgroup)
http://www.db4odev.com/newsarchive/search.cmd (search function for the above)
Can you see holiday breaks in the five year track record?

(3) When db4o stores object trees it does indeed store all reachable objects. If you do not want a field to be stored, you can decorate it with the [Transient] attribute (or configure your own attributes that you want to be used for "Transient"). If you do not want objects of a certain class to be stored, you would implement the TransientClass marker interface.

(4) If you want state restored during instantiation of an object, like for a Connection object, we provide two plugin interfaces to place your own code: A reflector interface (currently being revised and enhanced for 4.4) and a translator interface.

(5) Indeed we do not supply SQL querying yet but it's on the roadmap for the end of this year. We believe that object querying is superior to SQL because it can be checked better during compile time and refactored automatically by an IDE. db4o queries even allow you to run your own .NET code on the server as part of a query.

(6) The vendor lock-in is not that big, if you work against db4o: You create your classes and your objects, just like you have to do it anyway for your application. Storing objects is possible with very little code. You don't loose too much time for implementing the persistence part. In case you are unsatisfied with db4o, you can still do the big persistence work, that is necessary for other databases, later, after a prototyping phase with db4o. Since your class model is more mature now, you will probably even need less time than if you had started with SQL right away.

(7) We have one of the best experts for GUI development woldwide (Dave Orme - Eclipse VEP lead) working on a browsing and querying GUI for db4o. A first version will be available soon. For today, here is a quick hack by Rodrigo de Oliveira (inventor of the boo language), who is also associated with us:
http://sourceforge.net/projects/db4oboobrowser/

(8) Indeed you do not have to use your own IDs if you work with an object database. Objects simply reference eachother. If you do feel that you need IDs, I suggest that you use a persistent singleton (only one instance of a class stored) to generate it and a semaphore lock to make sure that IDs are unique, even if multiple clients request IDs at the same time.

(9) If you have a big enterprise database with a couple of dozen or hundred applications running against it, a relational database probably is a better choice: It's easier to tweak the system with views to map a new application to an outdated table scheme.
If you have a nice and clean class model, db4o does work good for very large applications. db4o databases can have a size of up to 254GB. Here is an example of an application on top of db4o with 20,000 classes:
http://www.db4o.com/about/customers/">http://www.db4o.com/about/customers/webradiance.aspx


Thanks for listening to me!


I would love to welcome you all in our public newsgroup for further discussions about db4o:
news://news.db4odev.com/db4o.users


Best,
Carl
--
Carl Rosenberger
Chief Software Architect
db4objects Inc.
http://www.db4o.com


Robert Jan van Holland wrote re: Native Objects Database
on 03-07-2005 9:28 AM
Thank you for your comment Carl,

This clarifies some issues, I guess!

I have subscribed to your newsfeed and I saw some interesting news items over there.
I have created a web application this weekend where the web applications creates one server instance of db40, and the aspx pages utilize that server object. Works very nice!

While working on this, and while reading your reply, three questions came up..
1. Does db40 provide some mechanism to traverse to the parent object of an object?
2. In your reply item nr. 6 you state that db40 could also help you in the development cycle of your class model.. and later on decide wether or not to use db40 or a conventional persistence layer.. In your experience, has this happened in real life with real customers? 'Cause I can imagine that customers don't like the idea of making that kind if decisions in a late stadium..
3. Can you point us to some documentation / examples of db40's reflector and translator classes?... i would like to find out some more about that :)

Kind regards,



Robert Jan van Holland wrote re: Native Objects Database
on 03-08-2005 8:51 AM
Yesterday I was playing a bit with db4o.. (yeah..in know...still.... but it just keeps me interested).
And another question popped up

How does db4o identifies an object? By its type name? Or by it's class signature?
Because, if i create a class User, and store some instances of that class in db4o.. and later on I decide to add a member field to the class. And I save a couple of instances of the updated class in db4o.


Are these User instances (the old, and the updated) of the same type?
Or is it not possible to store objects of different class signatures when objects with that name already exist in db4o..

Robert Jan van Holland wrote re: Native Objects Database
on 03-08-2005 11:19 AM
My colleague RJ pointed me to this discussion. After listening to him for a while some questions came up. I have to admit that I haven’t spent any time on this product and haven’t done any reading about this topic, so maybe my questions are very obvious. I wonder if some of you experts on this topic can share your opinion about the following:

Where within the architecture would you use this tool/technology??? Of course you will use this product as the physical database. Also using this product in de “data access” layer is very obvious, but what is next? Do you recommend using this technology also in the business layer or even service interface??

Personally I don’t think that’s the best way to go. For example, I wouldn’t share my “objects” at for instance my service interface layer.
If you agree with this: were would you make the mapping between the message that is used at the service interface level to the internal used object structure?

Maybe this question is totally of topic. But I wonder if you have some best practices for using this technology within the architecture (what layers) and I wonder what kind of architectures would best fit for this technology.
Robert Jan van Holland wrote re: Native Objects Database
on 03-13-2005 11:51 AM
Here are some answers to further questions:

(1) db4o currrently does not store back references to parent objects (unless you add them to your model of course). We will work on that. However you may want to use identity querying to find them, if you have a persistent instance of an object:

class Parent{
Child child;
}

class Child{

}

Assuming you have a persistent instance of Child in the variable "child" , you would do:
Query q = db.query();
q.constrain(typeof(Parent));
q.descend("child").constrain(child).identity();
ObjectSet objectSet = q.execute();


(2) Yes we do occasionally see users turn away from db4o after prototyping. My impression is that this is rarely a technical decision but more often a "I hold on to my seat"-decision. You never get fired for choosing Oracle, right?

(3) Samples for our translator interface can be found in our 3.0 download on the Downloadcenter page of our website. Within the download the translator sample code is in /db4o30/com/db4o/samples/translators/.
The 3.0 download comes with tons of more samples. We decided to discontinue them for 4.0 in order not to get people lost in the forest. In the long run we will migrate all old samples to our new interactive tutorial.
The reflector interface has just been rewritten completely for 4.4. The architecture should be well understandable from reading the sources of the com.db4o.reflect.net namespace (already available online in our CVS). Basically we wrap all calls for reflection through this interface. By taking our code, modifying it and plugging it back into db4o you can change the desired behaviour in any way you want. You can convert apples to oranges and back while you store them if you intend to do that.

(4) db4o identifies objects by identity and Type. You can add and remove fields to a Type whenever you like and continue to work with the stored instances.

(5) I am not a fan of setting up applications in layers. I believe in interfaces and delegation and I think that applications work best if they are designed as simple as possible.
We have improvements for db4o in the drawers for the coming year that will:
- let you express queries in plain C# (any .NET language) code without any references to db4o
- allow db4o to recognize when your objects are dirty
- allow db4o to load objects on demand when fields are accessed
With these changes db4o will be able to work within your objects while being completely invisible from the source code. I hope that all worries, where to place db4o, will be history with this approach.

Best,
Carl
--
Carl Rosenberger
Chief Software Architect
db4objects Inc.
http://www.db4o.com
TrackBack wrote re: Awesome Code generation !!!!
on 03-14-2005 6:57 AM

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Copyright © 2003-2008 BloggingAbout.NET
Powered by Community Server (Commercial Edition), by Telligent Systems