Login | Register
My pages Projects Community openCollabNet
Project highlights: Home - Download - Documentation - Contribute


When does a new object become available for querying? Or, why do we need the Individual.Insert() method?

Although there are ways by which newly constructed individuals could be registered within the current unit of work, none of them can make this registration after all subclasses are fully constructed. This means that the object could be accessible via queries while it is still undergoing construction – a source of very hard-to-find bugs.

Insert() provides an obvious indication of when the object becomes part of the model.

The alternative to the Insert() method that was considered was the use of a factory to automate the new object registration process. The unfortunate side-effect however is that either factories must be explicitly coded, constructors with parameters on Individuals have to be foregone, or else a non-typesafe variable-length argument list would have to be used on the factory’s create method.

Because a failure to call Insert() can be detected by the system, this approach was deemed the simplest and also the most transparent as to when the newly-constructed object becomes available through query.

If you would prefer to use a factory instead, coding this pattern using a dedicated class or a static method on each domain object class is trivial.

Why is an exception thrown if I try to update an object during its construction?

While it would be possible to allow this behaviour, it is highly likely that subtle bugs could be introduced because objects doing the updating would not be aware that the target object is not yet part of the model.

Why use GUID primary keys?

To fulfill Ubik’s goal of predictability, it is necessary that newly-created objects are indistinguishable from those stored in the database. If a piece of client code uses an object/its identity to form a query, then that identity needs to be distinct from that of all other newly-created objects. The fact that an object does not change its identity during its lifetime (as it would if its identity were generated upon database insertion) also helps to keep behaviour consistent.

Another worthwhile benefit of using GUIDs is that they make it possible that transparent online/offline smart client support could be added to Ubik without a great deal of additional complexity.

Space/performance considerations need to be made on a project-by-project basis, however they don’t usually preclude using GUIDs – consider that 1,000,000 GUIDs take approximately 16 MB of storage, compared to 4 MB for integers. These are both small numbers when considering filesystem storage on a modern server.

Why not use attributes for the mapping (a-la DLINQ)?

This is a feature currently being considered.

How do I create a bidirectional relationship?

Check out the example. One end of the relationship (either side of an M-N relationship, the 1- side in a 1-N) must be marked as virtual. This means that a query will be used to retrieve the relationship value from the virtual end on the client side. This is just to preserve the API and syntax while true bidirectional relationships are implemented.

Why is optimistic concurrency control restricted to one type in an inheritance hierarchy?

It doesn’t really make sense to allow multiple versions to be kept, as there is only one actual instance despite there being potentially many base classes making up an object. If this turns out to be required then it can be added.