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 関係は、実際には 1 対 1 になります。

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 が与えられていないためです。私の Insert 実装は次のようになります。

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

_session は NHibernate ISession です。新しいエンティティを保存し (正常に持続します)、セッションをフラッシュしたため、demInfo 変数に Id があると予想されますが、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 に答える