1
votes

I'm using NHibernate 3.3.3.4000 and SQL Server 2012.

I've searched for and not found an example of how to use mapping-by-code (loquacious) to configure optimistic concurrency using a SQL Server timestamp (i.e. rownumber) column.

I also use NHibernate's SchemaExport.Create() method to create the SQL Server database, so the mapping must result in a RowVersion column of type timestamp in the SQL Server table after NHibernate has created the database.

My DTO class is setup like this:

public class TestDto {
  public virtual Guid Id { get; set; }
  public virtual string Name { get; set; }
  public virtual Byte[] RowVersion { get; set; }
}

Here Ayende explains how to setup for optimistic concurrency using XML mapping and a SQL Server timestamp column. My attempts to mimic this using mapping-by-code (shown below) have all failed in one way or another.

http://ayende.com/blog/3946/nhibernate-mapping-concurrency

Here is a mapping-by-code example for optimistic concurrency, but it doesn't use a SQL Server timestamp column - and my attempts to guess at the changes required to make it work with a timestamp column have failed:

http://notherdev.blogspot.com/2012/01/mapping-by-code-concurrency.html

Here is my non-working attempt at mapping-by-code that is based as best as I can determine on the previous two articles:

  public TestMap() {
     Table( "Test" );

     DynamicUpdate( true );

     Id( x => x.Id, map => {
        map.Column( "ID" );
        map.Generator( Generators.GuidComb );
     } );

     Version( x => x.RowVersion, map => {
        map.Column( "RowVersion" );
        map.Generated( VersionGeneration.Always );
        map.UnsavedValue( null );
        map.Insert( true );
        //map.Type( new TimestampType() );       // Creates a datetime (not null) column.
        //map.Type( new BinaryBlobType() );      // Creates a VARBINARY(MAX) (not null) column.
        //map.Access( Accessor.Field );          // Causes error: Could not find property nor field 'RowVersion' in class 'SQC.Repository.Dtos.DataGroupDto'
     } );

     Property( x => x.Name, map => {
        map.Column( "Name" );
        map.NotNullable( true );
     } );
  }

When I uncomment this line the created table has RowVersion as "datetime (not null)" - and I need a SQL Server timestamp type.

map.Type( new TimestampType() );       // Creates a datetime (not null) column.

When I uncomment this line the created table has RowVersion as "VARBINARY(MAX) (not null)" - and I need a SQL Server timestamp type.

map.Type( new BinaryBlobType() );      // Creates a datetime (not null) column.

When I uncomment this line I get this error at runtime "Could not find property nor field 'RowVersion' in class 'TestDto'".

map.Access( Accessor.Field );

I hope someone can explain how to make this work using mapping-by-code (loquacious). The project is heavily committed to mapping-by-code, so Fluent NHibernate is not an option for us.

1

1 Answers

0
votes

get rid of the "map.Access( Accessor.Field );" This tells nhibernate to use a backing field to work with, however since you are using an auto property, there is no backing field. Either dont have it, or just use Accessor.Proper