The Tigris site will receive a major upgrade the evening of Monday, December 1, beginning at 8:30 pm PST. Downtime is projected to be about ten hours.
Further details in the announcement
FAQ
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.