tags:

views:

27

answers:

3

I have a mapping like this

<class name="UserFileSummary" table="UserFile" lazy="false">
   <id name="FileId" column="UserFileId" type="int">
      <generator class="identity" />
   </id>...

and a property in the c# object like this

public long FileId { get; set; }

What I don't understand is why when I get an instance using

var myFile = session.Get<UserFileSummary>(id)

change a field value and then save it like this

myFile.myProperty = newValue
session.Save(myFile)

I get an error saying the the Id have been altered from 1 to 1. There are some posts around about this, but this is a simple int column (identity 1, 1). I must have made some basic error, please can anyone help out. Thanks

I've added this bit as an edit as the question turns out to be a non question

The FileId property is type long, and the mapping is type int, that is why altered from 1 to 1 is a problem.

Please give me some feedback if you want me to delete this question, thanks everyone :)

+4  A: 

The only thing I can point out from your code is the use of Save for updating an existing entity.

You could avoid calling explicitly the Save method for an entity that's alredy present on the session. Your changes will be automatically persisted when you flush the session.

If you insist to explicitly call the update method I'd say you should use SaveOrUpdate.

Claudio Redi
Thanks, I am using a repository pattern, so I don't really call save. Not sure what is causing this. :)
Mark Dickinson
When I was removing the private setter stuff, I noticed that the id field was a long data type. Obviously the message "altered from 1 to 1" makes sense in this context and would be a problem. Now I have it all as int it works fine using my repository pattern. Sorry for wasting your time :)
Mark Dickinson
No problem :) glad that you finally figure it out.
Claudio Redi
+1  A: 

First, make the setter on the property private; the project will fail to compile if you have any code that mistakenly sets it. This is a good practice anyway. But it's not foolproof because there could be code inside the class that sets it, so you'll have to check for that.

public int FileId { get; private set; }

Second, closely examine the mapping file to make sure that you haven't mapped the field twice.

Jamie Ide
that needs to be <code>protected</code> for NHibernate to pick it up.
Rafael Belliard
No it doesn't. NHibernate sets the properties using reflection so it can access a private setter. All of my objects that use identity keys have private setters.
Jamie Ide
Hmm, tried it, but it messes a lot of other stuff up, and I have loads of other projects where Id is read write, with no issues.
Mark Dickinson
When I was removing the private setter stuff, I noticed that the id field was a long data type. Obviously the message "altered from 1 to 1" makes sense in this context and would be a problem. Now I have it all as int it works fine using my repository pattern. Sorry for wasting your time :)
Mark Dickinson
In my opinion, an identifier with a non-private setter in an NHibernate application using database generated (identity) IDs is a significant design flaw. But I'm glad you were able to find the problem.
Jamie Ide
A: 

The error in my case was due to the data type being a long (int64) in the database and being mapped to an int (int32) in the mapping. This meant that the real value chaned whenever the object was saved, thus breaking the identifier. Thanks to everyone whoe helped out.

Mark Dickinson