I have a simple many-to-many relationship between the User class and the Place class. This relationship is represented by the User's "Neighbourhood" property
public class User
{
public virtual IList<UserPlace> Neighbourhood { get; set; }
}
The UserPlace class is just a component that adds a single piece of information to the relationship between a User and a Place:
public class UserPlace
{
public virtual User User { get; set; }
public virtual Place Place { get; set; }
public virtual bool IsDefault { get; set; }
}
The relationship is mapped as follows:
public class UserMappings : ClassMap<User>
{
//... other mappings
HasMany(x => x.NeighbourHood)
.Component(c =>
{
c.Map(x => x.IsDefault);
c.References(x => x.Place).Cascade.None();
}
).Not.LazyLoad().Cascade.SaveUpdate();
}
When a user is created a number of Places are loaded from the database and added to the user, with one of these being set to default. When the user is persisted, the associated UserPlace entities are also persisted.
The problem I'm experiencing is that each Place entity associated with a UserPlace is also updated. That's not the desired effect, and I've tried preventing the Cascade to Place from taking place (pun not intended) by setting Cascade to None()... this doesn't change anything, however.
I've only managed to stop this update from taking place by specifying that each property on Place should not be updated ([PropertyName].Not.Updated()). This works, but it's not a solution.
Does anyone have any ideas on how I can prevent this from happening?
Edit: The Place entity mapping has DynamicUpdate() specified as well - so the entity really shouldn't change when a user is saved.
PS! I don't think it makes a difference to this scenario (but I may be wrong!), but consider this also: The Place entities are loaded outside of NHibernate (using ADO.NET and a stored procedure, because of some geospatial querying I couldn't do with NHibernate) and then attached to the session by calling Session.Update() on each entity.
This is not a cascading problem. NH updates the places because you call
session.Update
with each place. What you write in the PS is absolutely related to the problem.When you call update on a detached entity NH can't know if the state of the entity actually changed or not. To avoid querying the data before updating (two database round-trips) it blindly updates the data.
To avoid this:
SelectBeforeUpdate
in fluent)session.Merge(place)
. It also performs a query before updating. Note that it has a return value which needs to be used.session.Load(place.Id)
to create a proxy of the place in question and assign it (note that NH loads the place again when accessing the proxy's properties)session.Lock(place, LockMode.None)
to put the objects into the session.