在nhibernate中,无法更新子对象列表

时间:2010-12-10 02:51:45

标签: c# asp.net-mvc nhibernate fluent-nhibernate

我有 x ,其中 objectX 类型的对象具有 ListOfObjectYs 属性

List<objectY>

nhibernate映射如下所示:

    public ObjectXMap()
    {
        HasMany(x => x.ListOfObjectYs).AsBag().Inverse(); 
    }

当我去保存它时,我在 objectX 上更改了一些属性,然后有:

    Session.SaveOrUpdate(x);

现在我需要更新这个列表的属性。我得到一个新的objectYs列表,我想用一个新列表替换现有的objectY列表。我需要这样做吗?

  foreach (ObjectY y in x.ListOfObjectYs)
                {
                   Session.Delete(y);
                    deleted = true;
                }
                if (deleted)
                {
                   _session.Flush();
                }
                x.ListOfObjectYs.Clear();

                foreach (ObjectY y in newObjectYList)
                {
                    x.ListOfObjectYs.Add(y);
                   Session.SaveOrUpdate(y);
                }
                _session.Flush();

我的问题是:

  1. 在添加新内容之前,我是否必须删除所有内容并刷新。
  2. 我是否需要在
  3. 之间进行所有这些增量保存

    是否有更好的方法来执行此更新,我需要更新对象(属性),但也更新列表中存在全新列表的属性(意味着需要删除和添加项目)。

2 个答案:

答案 0 :(得分:4)

你的问题的答案是否定的。如果要替换列表,则应清除它并添加新项目。如果您将cascade设置为all-delete-orphan,就像在James Kovacs的回答中那样,那么当刷新会话时,对集合的更改将保持不变。

了解NHibernate中Save,Update和SaveOrUpdate的含义非常重要:

  • 保存 - 使新对象持久化
  • 更新 - 使更改的分离对象持久化
  • SaveOrUpdate - 根据对象标识符的未保存值保存或更新

另见Manipulating Persistent Data

假设所有对象都在同一个会话中加载,那么替换一个集合可能很简单:

x.ListOfObjectYs.Clear();
foreach (ObjectY y in newObjectYList)
{
    x.ListOfObjectYs.Add(y);
}
_session.Flush();

答案 1 :(得分:3)

您需要在HasMany()上使用级联。如果子对象完全由父对象拥有,则Cascade.AllDeleteOrphan()是一个不错的选择。这种方式在父级上的保存,更新和删除会自动级联到子对象,从而无需复杂的foreach块。有了这个,只需更新您的收藏并提交您的交易。 NHibernate将负责其余部分。

更新:要修改列表,只需像往常一样使用.NET集合添加和删除列表中的项目。例如:

public void RemoveY(ObjectY someY) {
    ListOfObjectYs.Remove(someY);
}

public void AddY(ObjectY someY) {
    ListOfObjectYs.Add(someY);
}

public void ClearAllY() {
    ListOfObjectYs.Clear();
}

提交事务时,对ListOfObjectYs集合的任何更改都将与父ObjectX一起保留。