c# - NHibernate SaveOrUpdate 子集合未使用标识 ID 更新

标签 c# .net nhibernate fluent-nhibernate

我显然遗漏了一些东西(希望很明显),到目前为止我在 Google 上运气不好。

我有一个父子关系映射如下

简化的父 map

  public sealed class ParentMap : ClassMap<ParentEntity>
  {
    public ParentMap()
    {
      Table("Parent");
      Component(x => x.Thumbprint);
      Id(x => x.Id).GeneratedBy.Identity();

      Map(x => x.ServeralNotNullableProperties).Not.Nullable();

      HasMany(x => x.Children).KeyColumn("ChildId")
                              .Inverse()
                              .LazyLoad()
                              .Cascade
                              .AllDeleteOrphan();

      References(x => x.SomeUnrelatedLookupColumn).Column("LookupColumnId").Not.Nullable();
    }
  }

简化子图

  public sealed class ChildMap : ClassMap<ChildEntity>
  {
    public ChildMap()
    {
      Table("Child");
      Component(x => x.Thumbprint);
      Id(x => x.Id).GeneratedBy.Identity();

      Map(x => x.MoreNotNullableProperties).Not.Nullable();

      References(x => x.Parent).Column("ParentId").Not.Nullable();
    }
  }

简化的服务方法步骤

然后我有一个服务方法,它检索 Parent 并通过一些域方法添加一个新的 Child。底层的 NHibernate 代码归结为:

1) 在 WCF AfterReceiveRequest (IDispatchMessageInspector) 上打开 session

_sessionFactory.OpenSession();

2) 通过 .Query 检索现有的 parent 实例

_session.Query<ParentEntity>()
        .Where(item => item.Id == parentId)
        .Fetch(item => item.SomeLookupColumn)
        .First();

3) 通过域对象方法将新的“子”实体添加到“父”,例如...

public ChildEntity CreateChild()
{
  var child = new ChildEntity{ Parent = this };

  Children.Add(child);

  return child;
}

4) 最终调用“父”实体上的 SaveOrUpdate。

 // ChildEntity Id is 0
 _session.SaveOrUpdate(parentEntity)
 // Expect ChildEntity Id to NOT be 0

注意:使用 SaveOrUpdate Does 将更改保存到数据库;使用 Merge 会导致下面提到的 TransientObjectException。

5) 最后,事务在 WCF BeforeSendReply (IDispatchMessageInspector) 上提交

 _session.Commit();

问题

通常在保存实体时,在调用 SaveOrUpdate 之后,所述实体的 Id 反射(reflect)由 INSERT 语句生成的身份。但是,当我将新的子实体添加到现有父实体时,Children 中的关联实体未分配 ID。我需要将此 ID 传递回调用方,以便后续调用导致更新而不是额外的插入。

为什么 NHibernate 不更新底层实体? 我是否明确必须对 child 调用 SaveOrUpdate(如果是这种情况,那很糟糕)?

对此事的任何想法都非常感谢。谢谢!

编辑 我应该注意,新的子实体正在按预期保存;我只是没有取回分配的 ID。

更新 尝试按照下面 Michael Buen 的建议切换到 .Merge(~) ;导致 TransientObjectException 告诉我在调用合并之前显式保存修改后的子实体。我也尝试过 .Persist(~) 无济于事。非常感谢任何额外的见解。

object is an unsaved transient instance - save the transient instance before merging: My.NameSpace.ChildEntity

最佳答案

我终于抽出时间来研究 NHibernate 代码……发生这种情况的原因是有道理的……简短的回答——级联操作是在 Session.Commit() 上处理的;在上述服务操作完成后。因此,在服务方法返回更新后的子实体时,我的子对象尚未刷新以反射(reflect)分配的 ID。

事实证明,如果我需要立即知道 Id,我必须直接在子实体上调用 SaveOrUpdate。

关于c# - NHibernate SaveOrUpdate 子集合未使用标识 ID 更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5629358/

相关文章:

.net - 并行 linq 中的 let 子句是否强制并行评估?

.net - 为什么并行堆栈不显示任何任务?

NHibernate:向 child 级联保存不插入

linq - NHibernate Linq 提供者和 take() skip() 与急切获取

c# - 从 C# 中的不同线程启动计时器

c# - 长时间运行的应用程序变慢

C# 仅根据第一个字母对字符串进行排序

c# - 如何在 ASP.NET Web API 核心中全局启用 CORS

c# - 得到一个整数?从数据库使用 DbDataReader

sql-server - 使用 Sqlite In Memory DB 进行单元测试 MSSQL-DB