如何强制NHibernate不更新集合中的所有对象

时间:2010-02-22 15:20:09

标签: nhibernate hibernate orm

如果我只更改该集合中的一个元素,如何强制NHibernate不为集合中的每个元素生成UPDATE。这是:

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; }
}

映射:

<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>

更新集合元素的代码:

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);

DbManager.SaveObject中的代码只是打开新会话并使用SaveOrUpdate来更新对象。

如果我从Slaves集合中更改其中一个元素然后尝试更新master,NHibernate会生成SQL以更新Slaves集合中的所有元素。但我只需要更新一个元素。

谢谢。

3 个答案:

答案 0 :(得分:1)

您可能会看到多余的多对一更新。在映射一对多集合时,必须选择哪一方是该关系的所有者。在您的示例中,关系的两个方面都认为他们拥有它!

您需要使用inverse="true"向您的set元素添加属性。该指令告诉NHibernate不要从关系的那一端更新集合。

答案 1 :(得分:0)

尝试使用access =“backfield”而不是access =“property”。

答案 2 :(得分:0)

您正在重建瞬态集合,因为Master.Slaves仍然是原始集合。

这不会在新会话中发生。

如果要在保存后更新同一会话中的实体,则应该session.Refresh()该实体。您的DBManager.SaveObject方法可以在保存后进行刷新。

DbManager.SaveObject<T>( T entity )
{
    session.Save( entity );
    session.Refresh( entity );
}