插入新的NHibernate实体并立即分配给父级

时间:2013-01-28 17:16:54

标签: nhibernate mapping-by-code

我的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关系遗漏给Booklet,因为我不需要遍历我的实体那个方向。 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"}

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

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

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

1 个答案:

答案 0 :(得分:0)

我已经解决了我的问题。事实证明,使用Sequences for 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" }));
});

现在我的测试没有例外。