Domanda

I have parent and child objects BOOKLET and DEMOGRAPHICS_INFO in my Oracle database mapped as follows in my data layer:

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");
    ...
}

I have intentionally left out the DemographicsInfo relationship to the Booklet because I don't need to traverse my entities that direction. The ManyToOne relationship will actually be a one-to-one.

I have written a test to ensure I can create a DemographicsInfo and immediately assign it to its parent Booklet, and that looks like this:

[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);
}

When I call Save(), I get the following exception:

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

This is because the demInfo object is not given an Id upon Insert(). My Insert implementation looks like this:

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

Where _session is an NHibernate ISession. Because I have both Saved the new entity (it persists successfully) and Flushed my session, I would expect my demInfo variable to have an Id, but it remains 0, which is a foreign key violation when I try to save my parent object. Am I overlooking a step here? Should I rethink my pattern for adding a new child to an existing parent?

È stato utile?

Soluzione

I have solved my issue. As it turns out, the Oracle convention of using Sequences for Id column values and populating them using Triggers on row insert disallows NHibernate from learning the Id upon persisting an entity. I added a Sequence Generator to my Id maps and Insert() now updates the Id on my transient entity upon save so I can assign the DemographicsInfo to my Booklet.DemographicsInfo.

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

Now my test passes with no exceptions.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top