NHibernate updating version when the entity was not changed

761 views
Skip to first unread message

steves

unread,
Jul 21, 2009, 3:43:34 PM7/21/09
to nhusers
Hi,

I have entity User with one-to-many relationship to
UserToUserCategories. When I load user from database, do not change it
and than flush the session, NHibernate will performs UPDATE of the
user and increment it's version. It seems to me as unwanted behaviour,
imagine that I load hundred of users and NHibernate would update them
all when flushing. Here is the code:

public abstract class EntityBase
{
public virtual Guid Id { get; set; }
public virtual int Version { get; set; }
}

public class User : EntityBase
{
public virtual IList<UserToUserCategory> UserToUserCategories
{ get; set; }
}

public class EntityBaseMap<T> : ClassMap<T> where T : EntityBase
{
public EntityBaseMap()
{
this.OptimisticLock.Version();
this.DynamicUpdate();
this.Id(t => t.Id);
this.Version(t => t.Version);
}
}

public class UserMap : EntityBaseMap<User>
{
public UserMap()
{
this.HasMany(u => u.UserToUserCategories)
.NotFound.Ignore()
.Cascade.All()
.LazyLoad()
.AsBag()
.WithTableName("UserToUserCategory");
}
}


session = SessionSource.CreateSession();
var user = (from u in session.Linq<User>() select u).FirstOrDefault();
session.Flush(); // here NHibernate does UPDATE statement of user's
version

Is this mapping incorrect? What am I missing?

Markus Zywitza

unread,
Jul 22, 2009, 10:20:17 AM7/22/09
to nhu...@googlegroups.com
Can you try with a backing field for Categories initialized with a List<..>-instance?
 
I had strange issues before with autoproperties on collections.
 
-Markus

2009/7/21 steves <steve....@gmail.com>

Fabio Maulo

unread,
Jul 22, 2009, 10:24:11 AM7/22/09
to nhu...@googlegroups.com
for autoproperties and access to field you can use
access="backfield"

2009/7/22 Markus Zywitza <markus....@gmail.com>



--
Fabio Maulo

Stefan Steinegger

unread,
Jul 22, 2009, 10:33:06 AM7/22/09
to nhusers
If NH does unnecessary updates, it is mostly due to implicit changes
within the entity. The properties must always return the exact value
that has been set by NH, if it is a collection, the entity must return
the same instance as set by NH, unless NH treats it as a change and
updates the database.

I never saw any issues with {get; set;} (which does not mean that
there aren't.)

Your code looks fine to me, but I don't know Fluent much. Is this
really the full code to reproduce the problem? You didn't leave
anything away because you thought it is irrelevant? For instance a
property getter or setter implementation?

On 22 Jul., 16:24, Fabio Maulo <fabioma...@gmail.com> wrote:
> for autoproperties and access to field you can useaccess="backfield"
>
> 2009/7/22 Markus Zywitza <markus.zywi...@gmail.com>
>
>
>
> > Can you try with a backing field for Categories initialized with a
> > List<..>-instance?
>
> > I had strange issues before with autoproperties on collections.
>
> > -Markus
>
> > 2009/7/21 steves <steve.side...@gmail.com>

steves

unread,
Jul 22, 2009, 3:09:53 PM7/22/09
to nhusers
Thank you guys, you got it.

The actuall code returns the collection as new ReadOnlyCollection
(this.userToUserCategory) that is created every time the getter is
called. So I added:

this.HasMany(u => u.UserToUserCategories).Access.AsCammelCaseField
()....

and it works perfect. Also lazy loading, which was working
incorrectly, now works fine. Now my question seems silly to me :(,
anyway thanks.

Fabio Maulo

unread,
Jul 22, 2009, 3:38:27 PM7/22/09
to nhu...@googlegroups.com
I strongly recommend the usage of the GhostBuster to prevent all this kind of surprise (it is only one test).



--
Fabio Maulo
Reply all
Reply to author
Forward
0 new messages