0
votes

I'm using NHibernate 4.0.0.4000 (with mapping by code) and SQL Server 2012.

I have to access tables which (among others) contain a timestamp (otherwise also known as rowversion) column. Until now I could simply ignore the column by not using it in my Entity/Mapping.

Now I want to use it to see, which rows have changed since the last time I checked the table in question.

Since timestamp may only be changed by SQL Server, any INSERT / UPDATE statements generated by NHibernate must ignore this column. I didn't find a solution for this problem.

My entity:

public class TblAnwendungsbelegposition {
    public virtual int ANWBID { get; set; }
    // Other properties cut out for readability
    public virtual byte[] upsize_ts { get; set; }
}

My mapping:

public class TblAnwendungsbelegpositionMap : ClassMapping<TblAnwendungsbelegposition> {

    public TblAnwendungsbelegpositionMap() {
        Table("tbl_anwendungsbelegposition");
        Schema("dbo");
        Lazy(true);
        Id(x => x.ANWBID, map => map.Generator(Generators.Identity));
        //Other properties cut out for readability
        Property(x => x.upsize_ts, map => map.Access(Accessor.ReadOnly));
    }
}

Result for this version:

Cannot update a timestamp column

as an error message during reading (on the automatic Session.Flush() on closing the using-statement wrapping the db connection).

When I remove the accessor in the mapping I can read without problems, but when I insert a new line into the table, I get the message

Cannot insert an explicit value into a timestamp column. Use INSERT with a column list to exclude the timestamp column, or insert a DEFAULT into the timestamp column.

When I change the set; to private set;, I get the message during the initial BuildSessionFactory();

The following types may not be used as proxies: PigTool.Entities.TblAnwendungsbelegposition: method set_upsize_ts should be 'public/protected virtual' or 'protected internal virtual'

When I remove the set; from the entity-property, I get the message during the initial BuildSessionFactory();

Could not find a setter for property 'upsize_ts' in class 'PigTool.Entities.TblAnwendungsbelegposition'

Does anyone have an idea how I can successfully read rows containing this readonly column, while retaining the ability to generate new rows? I'd prefer not to have two entities/mappings per relevant table, where one doesn't contain the timestamp property for everyday work and one which has it, but is only ever used for reading.

1

1 Answers

0
votes

I finally found a solution.

In the mapping exchange the

        Property(x => x.upsize_ts, map => map.Access(Accessor.ReadOnly));

with

        Version(x => x.upsize_ts, map => 
        {
            map.Column(c => 
            {
                c.SqlType("timestamp");
                c.NotNullable(false);
            });
            map.Type(new BinaryBlobType());
            map.Generated(VersionGeneration.Always);
            map.UnsavedValue(null);
        });