We are developing our database in order to support record versioning and in order to query the data valid in a particular date/time. I remember that in an older version of DataObjects record versioning was implemented. With version 4.6 what technique best fit to implement this feature?

asked Jan 17 '13 at 09:29

sluzardi's gravatar image


2 Answers:

Hello Stefano,

DataObjects.Net 4.6 provides various options related to row-version handling.

The most simple approach is to apply VersionAttribute to persistent field at hierarchy root:

[Field, Version]
int Version { get; private set; }

In this case DataObjects.Net will automatically increment that field once per-transaction if entity has been changed.

You can use DateTime fields as well.

Another option is to manually deal with version fields:

[Field, Version(VersionMode.Manual)]
int Version { get; private set; }

protected override bool UpdateVersion(Entity changedEntity, FieldInfo changedField)
    // This method is called when DataObjects.Net requests version change.
    Version = Version + 2;
    // If true is returned row-version is considered changed.
    return true;

answered Jan 18 '13 at 04:39

Denis%20Krjuchkov's gravatar image

Denis Krjuchkov

Hi denis

with this implementation you increment the row version, but you cannot access previous releases of record and you can't implement soft delete. I am looking for a solution that maintains coherent graphs for each version.

Since now I resolved the query problem using session.OverrideQueryRoot(QueryRootBuilder) but real problems lies on updates and delete.


(Jan 18 '13 at 05:53) sluzardi sluzardi's gravatar image

OK. I've got your question. Unfortunately there is such facility available in DO 4.x.

(Jan 28 '13 at 03:05) Denis Krjuchkov Denis%20Krjuchkov's gravatar image

I've implemented this myself by letting every "entity" under the hood consist of two entities, "Item" and "ItemVersion", where Item is the item you have a reference to if you need to reference the item, ex. in an association, id for an url etc, and ItemVersion is a specific version of that Item. ItemVersion contains the actual fields. It's a strict insert-only model, updates and deletes are "forbidden".

Apart from the actual data, ItemVersion also stores timestamp, if the item is deleted, by who etc (simplified, I've got a EditVersion attached to group edits performed at the same time.) To assist operations on this I've created some helper methods and/or properties, and added some LinqRewriters to make querying easier.

There are some limitations though, one is performance. It's a work-in-progress, but I'm analyzing the sql queries continuosly, and redoing indexes. Ex, in ItemVersion I've "copied" some field from the EditVersion to avoid cross-referencing with EditVersion when querying.

It's a bit complex, but the helpers speed things up quite a bit, and I've got good versioning - by wrapping my queries with

using(var rs = new ReadVersionScope(DateTime.UtcNow.AddDays(-2)) {}

I've got an instant replay of what the db looked like 2 days ago. By querying EditVersion I've got an instant view of what has changed, by who, when and what etc. It's quite powerful.

I'm not saying that my version is the best version, but it's the way I've chosen. I haven't tried it with real data yet, only with som generated test data (which seemed to work quite well, actually. Good indexes and good queries are your best friend for performance in this case :) )

answered Jan 29 '13 at 05:31

Onkelborg's gravatar image


Thank you

My implementation is a little different. I clone programmatically the records to save old versions and I create some classes to manage versioning of associations. Thanks the helper idea that I used with a specific QueryRootBuilder implementation in order to query old record and association versions.

(Jan 29 '13 at 07:09) sluzardi sluzardi's gravatar image

It sounds kind of similar actually, but I haven't implemented mine using QueryRoot, and I have two entities instead of one :)

(Jan 29 '13 at 07:16) Onkelborg Onkelborg's gravatar image
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview


Once you sign in you will be able to subscribe for any updates here



Asked: Jan 17 '13 at 09:29

Seen: 1,803 times

Last updated: Jan 29 '13 at 07:16

powered by OSQA