0

我的 Oracle 数据库中有父对象和子对象 BOOKLET 和 DEMOGRAPHICS_INFO,在我的数据层中映射如下:

public BookletMapping()
{
    Table("BOOKLET");
    Id(x => x.Id, m => m.Column("ID");
    ...
    ManyToOne(x => x.DemographicsInfo, m => m.Column("DEMOGRAPHICS_INFO_ID"));
}

public DemographicsInfoMapping()
{
    Table("DEMOGRAPHICS_INFO");
    Id(x => x.Id, m => m.Column("ID");
    ...
}

我故意省略了与小册子的 DemographicsInfo 关系,因为我不需要遍历我的实体那个方向。ManyToOne 关系实际上是一对一的。

我编写了一个测试,以确保我可以创建一个 DemographicsInfo 并立即将其分配给它的父 Booklet,它看起来像这样:

[Test]
public void ShouldSaveCorrectEntity()
{
    var booklet = _unitOfWork.Get<Booklet>(4);
    var demInfo = new DemographicsInfo();
    _unitOfWork.Insert(demInfo);
    booklet.DemographicsInfo = demInfo;
    _unitOfWork.Save();

    demInfo.Id.ShouldNotEqual(0);
}

当我调用 Save() 时,我得到以下异常:

{"ORA-02291: integrity constraint (<schema>.BOOKLET_DEMOGRAPHICS_INFO_FK1) violated - parent key not found\n"}

这是因为在 Insert() 时没有为 demInfo 对象指定 Id。我的插入实现如下所示:

public void Insert<T>(T entity)
{
    using (var transaction = _session.BeginTransaction())
    {
        _session.Save(objectToSave);
        _session.Flush();
        transaction.Commit();
    }
}

其中 _session 是一个 NHibernate ISession。因为我已经保存了新实体(它成功保存)并刷新了我的会话,所以我希望我的 demInfo 变量有一个 Id,但它仍然为 0,当我尝试保存我的父对象时,这违反了外键。我在这里忽略了一步吗?我应该重新考虑将新孩子添加到现有父母的模式吗?

4

1 回答 1

0

我已经解决了我的问题。事实证明,对 Id 列值使用序列并在行插入时使用触发器填充它们的 Oracle 约定不允许 NHibernate 在持久化实体时学习 Id。我在我的 Id 映射中添加了一个序列生成器,并且 Insert() 现在在保存时更新我的​​瞬态实体上的 Id,因此我可以将 DemographicsInfo 分配给我的 Booklet.DemographicsInfo。

Id(x => x.Id, m =>
{
    m.Column("ID");
    m.Generator(Generators.Sequence, a => a.Params(new { sequence = "SEQ_TABLE_ID" }));
});

现在我的测试无一例外地通过了。

于 2013-01-28T19:54:42.993 回答