I am trying to achieve a HasMany mapping with a non-nullable key column.
My mapping looks like this:
public void Override(AutoMapping<DataExportTable> mapping)
{
mapping.Table("data_export_tables");
mapping.Id(x => x.Id).Column("data_export_tables_id")
.GeneratedBy.Sequence("SQ_DATA_EXPORT_TABLES_ID");
mapping.HasMany(x => x.Columns)
.KeyColumn("table_id")
.Not.KeyNullable()
.Not.KeyUpdate()
.Cascade.AllDeleteOrphan();
}
The code to save the entity looks like this:
var table = new DataExportTable("table_name");
table.Columns.Add(new DataExportColumn("column_name"));
session.Save(table);
transaction.Commit();
This throws an exception:
NHibernate.Exceptions.GenericADOException: could not execute batch command.[SQL: SQL not available] ---> Oracle.DataAccess.Client.Orac leException: ORA-01400: cannot insert NULL into ("MYSCHEMA"."DATA_EXPORT_COLUMNS"."TABLE_ID")
Now, I read quite a few posts about this topic and the generally accepted solution seems to be to make the reference bi-directional, i.e. adding a Table property to DataExportColumn and setting that.
Another "hack" is to make the foreign key column nullable.
That's not what I want. I want NHibernate to insert the ID directly in the INSERT statement.
According to the log file, NHibernate certainly knows the ID at the time it executes the INSERT statement:
NHibernate: select SQ_DATA_EXPORT_TABLES_ID.nextval from dual
NHibernate: Batch commands:
command 0:INSERT INTO data_export_tables (NAME, data_export_tables_id) VALUES (:p0, :p1);:p0 = 'table_name' [Type: String (0)], :p1 = 93 [Type: Int32 (0)]NHibernate: Batch commands:
command 0:INSERT INTO data_export_columns (NAME, data_export_columns_id) VALUES (:p0, :p1);:p0 = 'column_name' [Type: String (0)], :p1 = 1228 [Type: Int32 (0)]
As you can see, NHibernate simply ommits the table_id column, although the ID is well known - NHibernate passed it as a parameter to the first insert statement...