0

I'm trying to create a DB Table, using an NHibernate *hbm.xml mapping file, that will have a Versioning Column for concurrency check. The Versioning column should be a nullable Integer.

Although the Database is created just fine, using the mapping file as reference, the following happen: * The first record is inserted with a NULL value as the Version * The update of the previously inserted records fails with a "Stale Data" exception

In other words, no matter what I do, the Version column is always NULL. I'm somewhat new to the Concurrency Control using NHibernate, so I don't quite understand what I'm doing wrong..

If I use a Timestamp as a Version, everything works just fine. However, my requirement is to use an Integer.. Hence my problem.

This is my Mapping File:

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="true" auto-import="false" assembly="New1.Backend" namespace="New1.BO">
    <class name="Natrio" table="`Natrios`" schema="`dbo`">
        <cache usage="read-write" />
        <id name="Id" column="`Id`" type="System.Int32">
            <generator class="NHibernate.Id.Enhanced.TableGenerator">
                <param name="increment_size">200</param>
                <param name="segment_value">Natrios</param>
                <param name="optimizer">pooled-lo</param>
            </generator>
        </id>
        <version name="Version" column="`Version`" type="System.Nullable`1[[System.Int32, mscorlib]], mscorlib" generated="always" unsaved-value="0">
            <column name="`Version`" not-null="false" sql-type="int" />
        </version>
        <property name="Attribute" column="`Attribute`" type="String" not-null="false" length="100" />
    </class>
</hibernate-mapping>

Any thoughts and/or suggestions would be greatly appreciated!

1 Answers1

0

Why do you need nullable version column? In any case I believe the issue is caused by unsaved-value="0" in your mapping. As default value for nullable column is null - NHibernate thinks that value is already generated and so it's never assigned. You need to set it to null - unsaved-value="null" to make it work with nullable columns. And unsaved-value="0" makes sense for not-nullable types. But better omit this attribute completely and let NHibernate to s

Another issue with generated attribute. It's about DB generation - so always means that this value is generated automatically by DB. You should remove it or specify it as generated="never".

I believe the following mapping should work for you:

<version name="Version">
    <column name="`Version`" not-null="false" sql-type="int" />
</version>
Roman Artiukhin
  • 2,200
  • 1
  • 9
  • 19
  • Well, the nullable version column has to do with the Requirements for the System. I applied your suggestion, though, and no change... The Version column is still saved as NULL and when I update the record I face a Stale Data exception. – Queenferno Jun 07 '19 at 11:42
  • Fyi, again the exact same behavior is happening if I use the following mapping: ```xml ``` Notice the normal Integer (instead of a Nullable) I just don't know what its problem is. – Queenferno Jun 07 '19 at 11:50
  • Well. Not sure why it's not working for nullable type. But you last mapping is not correct - for `int` it should be `0` not `null` – Roman Artiukhin Jun 07 '19 at 12:01
  • Same thing with ```unsaved-value="0"``` . The NHibernate documentation stated that the Integer is the **default** type for a Version column, however it has absolutely no examples! Now I'm using a not-nullable ```System.Int32``` with a ```0``` unsaved value and nothing is changed. I just don't know what it needs from me. – Queenferno Jun 07 '19 at 12:20
  • Actually `generated="always"` means that this value is generated by DB. You should omit this attribute or specify it as `generated="never"` – Roman Artiukhin Jun 07 '19 at 13:16
  • Why though? I **want** it generated by the Database. At least, when I'm using a Timestamp as my type, I set ```generated="always"``` and it works like a charm, always taking a new value, whether I'm saving the value from within my application of via a raw SQL Query in an SQL Manager.. If I set it as ```generated="never"``` who will update it?? – Queenferno Jun 07 '19 at 13:33
  • And how do you expect it to be generated? Is there some built in type in DB for autoincremented int value? I guess if you want it DB generated than you need to manually create trigger that updates/inserts this value – Roman Artiukhin Jun 07 '19 at 13:41
  • Hm! I applied your suggestion with regards to the ```generated="never"``` setting. It worked (finally) when I'm saving records using my Application, automatically incrementing my Version. **However**, if I update a raw manually (via a SQL Manager), the Version remains the same (which can be problematic for our case). So... half way there! Yey!!! <3 – Queenferno Jun 07 '19 at 13:43