0

我正在使用带有 hbm 映射文件的 NHibernate 版本 3.1.0.4000。当我有一个包含包集合的实体并且我保存该实体以及添加到包中的所有项目时,它会很好地保存所有集合项目。但是,当我随后(在初始保存之后)将另一个项目添加到集合并保存实体时,它不会将新项目保存在集合中。我查看了 NHibernate 生成的 SQL,它创建了初始的 Insert SQL 语句,但它没有创建 Update SQL 语句来更新外键值。解决方案中的所有袋子都会出现此问题。

这是一个映射提取:

    <?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   default-lazy="false"
                   namespace="some_namespace"
                   assembly="some_assembly">

  <class name="Landing"
            table="[Landing]"
            select-before-update="true"
            optimistic-lock="version">
    <id name="Id"
        column="[Id]"
        unsaved-value="null">
      <generator class="assigned" />
    </id>

    <version name="Version"
            column="[Version]"
            unsaved-value="null" />

    <bag name="LandingPermits"
         cascade="all-delete-orphan"
         access="field.camelcase">
      <key column="[LandingId]" />
      <one-to-many class="LandingPermit" />
    </bag>

  </class>
</hibernate-mapping>

这是我的 NHibernate 存储库中的 Save 方法:

    public NHibernateRepository(ISessionFactory factory, string queriesAssemblyName = null, string clientName = null)
{
    this.sessionFactory = factory;
    this.queriesAssemblyName = queriesAssemblyName;
    this.clientName = clientName;

    if (!string.IsNullOrEmpty(this.queriesAssemblyName))
        LoadQueries();
}

public virtual void Save(IAggregateRoot entity)
{
    Save(new IAggregateRoot[] { entity });
}

public virtual void Save(IAggregateRoot[] entities)
{
    try
    {
        using (var session = OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {
                try
                {
                    foreach (var entity in entities)
                    {
                        if (entity.IsNew)
                            entity.AddedDateTime = DateTime.Now;
                        else
                            entity.UpdatedDateTime = DateTime.Now;

                        session.SaveOrUpdate(entity.GetType().Name, entity);
                    }
                    transaction.Commit();
                }
                catch (Exception e)
                {
                    transaction.Rollback();
                    throw e;
                }
                finally
                {
                    if (session.Connection.State == ConnectionState.Open)
                        session.Connection.Close();

                    session.Connection.Dispose();
                    session.Close();
                }
            }
        }
    }
    catch (GenericADOException e)
    {
        var sqlException = e.InnerException as SqlException;

        if ((sqlException != null) && (sqlException.Number == ForeignKeyExceptionNumber))
            throw new EntityInUseException("Save", sqlException);
        else
            throw new RepositoryException("Save", e.InnerException);
    }
    catch (StaleObjectStateException e)
    {
        throw new ConcurrencyException("Save", e, new Identity((Guid?)e.Identifier));
    }
    catch (Exception e)
    {
        throw new RepositoryException("Save", e);
    }
}

我尝试了一些事情,包括将 inverse 属性设置为 true,但没有成功。希望这是足够的信息,任何人都可以提供帮助。谢谢

4

1 回答 1

0

如果您的集合是inverse=false(默认),则意味着集合的所有者(父级)对关系负责。如果父项和子项都是 IAggregateRoot,则在上面的代码中不清楚,但如果它们都是 IAggregateRoot,则意味着当您将子项保存在不知道父项的会话中时,子项将被很好地保存但不会被添加到收藏。

如果您使用inverse=true,则孩子将对这段关系负责。在这种情况下,模型应该是双向的,您应该映射两端。

你在这里有几个选择...

  • 孩子真的是聚合根吗?也许它应该与它的父母一起坚持?
  • 使用双向关系并使用inverse=true
于 2014-02-21T09:17:40.710 回答