Search code examples
c#oracle-databasenhibernatenhibernate-mapping

How can I source an NHibernate composite key's values from an Oracle sequence using Mapping.ByCode?


Using NHibernate's Mapping.ByCode, how can I source the initial values of a composite key from Oracle sequences?

ComposedId(map =>
{
    map.Property(x => x.Column1);
    map.Property(x => x.Column2);
});

The below works for a single key, but ComposedId uses IComposedIdMapper, which doesn't seem to have an equivalent to IIdMapper's Generator:

Id<decimal>(x => x.Id, o =>
{
    o.Column("ID");
    o.Generator(Generators.Native, genMapping => genMapping.Params(new { sequence = "MY_SCHEMA.MY_ID_SEQ" }));
});

Solution

  • If one column is generated from a sequence incremented at each insert, it ought to be unique alone. So it could be mapped as a single column id.

    Composite id does not allow for generators because they are by essence assigned, by example to some primary keys of other tables, or to some enumerated value like a "type of the entity" combined a key of wome owner, a rank, whatever.

    You may still use a sequence for assigning one part of the composite id if you really have to, but you will have to call by yourself the sequence for getting its value and assigning it to your composite id. Use ISession.CreateSQLQuery("adequate sql for your db") for doing this. You may build your sql with the help of the dialect object, exposed by your session factory. (Call ISession.GetSessionImplementation().Factory.Dialect.GetSequenceNextValString("sequenceName").)

    But normally, if you want to use a sequence for an id, use a single column id, not a composite one.

    It looks to me quite wrong to use a composite-id with one column generated with a unique value: better avoid composite id whenever possible. If the value is unique, it does not need any additional column for being a primary key.

    By the way, in most cases, NHibernate will not care whether the mapped id is actually declared as a primary in the database or not, whether an association key is declared as a foreign key or not, ... It matters only if you use NHibernate for schema generation. So better map them in the way that makes more sense, unless you have some weird things preventing you to simplify them in the NHibernate mapping.