How to force NHibernate not to update all objects in collection
How to force NHibernate not to generate UPDATE for each element in collection if I change only one element of that collection. Here it is:
internal class Master
{
private int _id;
public string Name { get; set; }
public ISet<Slave> Slaves { get; set; }
public Master()
{
Slaves = new HashedSet<Slave>();
}
}
internal class Slave
{
private int _id;
public string Name { get; set; }
public Master Master { get; set; }
}
Mappings:
<class name="nHibernateTutorials.Slave, nHibernateTutorials" lazy="false">
<id access="field" name="_id" column="id">
<generator class="native"/>
</id>
<property access="property" name="Name" column="name"/>
<many-to-one access="property" name="Master" column="master"/>
</class>
<class name="nHibernateTutorials.Master, nHibernateTutorials" lazy="false">
<id access="field" name="_id" column="id">
<generator class="native"/>
</id>
<property access="property" name="Name" column="name"/>
<set access="property" name="Slaves" cascade="save-update">
<key column="master"/>
<one-to-many class="nHibernateTutorials.Slave, nHibernateTutorials"/>
</set>
</class>
Code that updates collection element:
Master m = new Master {Name = "Kenny"};
Slave s1 = new Slave { Name = "Cartman", Master = m};
m.Slaves.Add(s1);
Slave s2 = new Slave {Name = "Kyle", Master = m};
m.Slaves.Add(s2);
Slave s3 = new Slave {Name = "Stan", Master = m};
m.Slaves.Add(s3);
DbManager.SaveObject(m);
s1.Name = "Daisy";开发者_开发知识库
DbManager.SaveObject(m);
Code in DbManager.SaveObject simply opens new session and uses SaveOrUpdate to update object.
If I change one of the elements from the Slaves collection of master and then try to update master, NHibernate generates SQL for updating all elements in Slaves collection. But I need to update only one element.
Thank you.
You're probably seeing superfluous many-to-one updates. When you're mapping one-to-many collections, you must choose which side is the owner of the relationship. In your example, both sides of the relationship think they own it!
You need to add an attribute to your set element, with inverse="true"
. That directive tells NHibernate not to update the collection from that end of the relationship.
Try using access="backfield" instead of access="property".
You are resaving a transient collection, because Master.Slaves is still the original collection.
This would not happen in a new session.
If you want to update an entity in the same session after saving, you should session.Refresh() that entity. Your DBManager.SaveObject method could do a refresh after save.
DbManager.SaveObject<T>( T entity )
{
session.Save( entity );
session.Refresh( entity );
}
精彩评论