Making use of the [Version] attribute in Castle ActiveRecord is a really nice way of enabling your app to detect changes in data that may have happened in other apps. Usually, you’d just save your record and it’d be in the DB. Unfortunately, you may have inadvertently overwritten someone else’s updates. In more formal terms, it is a convenient way of solving data concurrency issues.
I've set up an example demonstrating (really simply) how to put this into practice.
Download
ARVersionApp.zip
Code
You'll notice in this class definition that I've made use of the [Version] attribute on one of the properties, rather than using the [Property] attribute.
[ActiveRecord ("DBRecord")]
public class DBRecord :ActiveRecordBase<DBRecord>
{
[PrimaryKey (PrimaryKeyType.Identity, "DBRecordId")]
public int Id { get; set; }
[Property ("Data", "String")]
public string Data { get; set; }
[Version("Version")]
public Int32 Version { get; set; }
}
This informs the ActiveRecord internals that this property can be used for versioning. If you run the sample application, it stops after the first update of the record. If you make use of Sql Enterprise Manager or the likes, modify the record that has been inserted (remember to change the version number as well), and then continue running the app by pressing enter. ActiveRecord throws a StaleObjectState exception if the Version field is different - indicating that something else has updated it. You'll need to do some checking on this exception that is thrown, however, as the actual exception thrown is a "generic" ActiveRecordException, and the inner exception is of type "NHibernate.StaleObjectStateException".
I turned on NHibernate's Sql logging to get an idea of the update statement being sent to the Sql server for the second update. You'll notice that the version field was automatically updated and does not need to be set by your code. I haven't actually checked out the NHibernate/ActiverRecord source yet, but I gather that it is comparing the rows affected by the statement to determine if a record was successfully updated.
UPDATE
DBRecord
SET
Version = 2, Data = 'This is the new data to be saved'
WHERE
DBRecordId = 13 AND
Version = 1
According to the official documentation here, the [Version] attribute can be used on properties of type Int64, Int32, Int16, Ticks, Timestamp or TimeSpan. I've also found the it works on a DateTime field, however, if your field in the table has milliseconds, a simple update causes an exception to be thrown, as the milliseconds are not kept by ActiveRecord/NHibernate. In addition, you need to manually set the version if you're making use of a DateTime type. All that being said, maybe using a DateTime field is not such a good idea :)