O/R Mapping meets Mission Critical

time to read 3 min | 480 words

Udi Dahan raise an interesting point regarding the use of O/R tools with insert-only databases. The idea being that you never delete / update from the database, but insert data with a timestamp.

I think that this is an extention to what Roy talked about regarding Temporal Data, if you care about the one in a million case, you can use triggers and a seperated table. If you need more sophicsticated approach, I think that the better way would be to use DDD's repositories and abstract it all away. I imagine that you could do things like this:

TemporalEmployeeRepository repos = new TemporalObjectRepository(...);
TemporalEmployee temporalEmployee = (TemporalEmployee)repos.GetRecentWithId(1);
temporalEmployee .Salary += 100;
repos.Save(temporalEmployee);//create a new record and save

The key to this interface that it allows you to explicitly works with temporal data, and hide the database implementation, this is good, but the title of the post is how to use the O/R tools to handle this.

Hiberante apperantely support this, but I'm not sure if NHiberante has this implementation. Looking at the code briefly seems to suggest that we have it for collectios and not for classes. Let assume for a moment that it doesn't have it, and that we need to add our own implementation to it.*

Accepting the premise above, let's see how we can implement this functionality in NHibernate. First, I would define a composite key that would include the object's id & timestamp. Since we are dealing with temporal data, the timestamp of an object is very much part of its identity. Then I would try to create the following methods to access the database:

TemporalEmployee GetRecentWithId(int id);
TemporalEmployee[] GetWithinRange(int id, Date start, Date end);
void Save(TemporalEmployee temporalEmployee);

The Save() method, for instance, could simply store DateTime.Now in the timestamp and call Session.Save(), which would insert a new row to the table. GetWithinRange() is also very easy to implement. I'm not 100% sure how to implement GetRecentWithId() efficently, but I should've an answer tomorrow.

* Of course, it also very likely that there is a built in solution for this, I'll email a question about it to the NHibernate list and see if anything has a better solution.