我正在尝试使用不可为空的键列实现HasMany
映射。
我的映射如下所示:
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();
}
保存实体的代码如下所示:
var table = new DataExportTable("table_name");
table.Columns.Add(new DataExportColumn("column_name"));
session.Save(table);
transaction.Commit();
这会引发异常:
NHibernate.Exceptions.GenericADOException:无法执行批处理命令。[SQL:SQL不可用] ---&gt; Oracle.DataAccess.Client.Orac leException:ORA-01400:无法插入NULL(“MYSCHEMA”。“DATA_EXPORT_COLUMNS”。“TABLE_ID”)
现在,我读了很多关于这个主题的帖子,普遍接受的解决方案似乎是将参考文档双向化,即向Table
添加DataExportColumn
属性并设置它。登记/>
另一个“黑客”是使外键列可以为空。
那不是我想要的。我希望NHibernate直接在INSERT语句中插入ID
根据日志文件,NHibernate在执行INSERT语句时肯定知道ID:
NHibernate:从双重中选择SQ_DATA_EXPORT_TABLES_ID.nextval NHibernate:批处理命令:
命令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:批量命令:
命令0:INSERT INTO data_export_columns(NAME,data_export_columns_id)VALUES(:p0,:p1);:p0 = 'column_name'[类型:字符串(0)] ,: p1 = 1228 [类型:Int32(0)]
正如您所看到的,NHibernate只是省略了table_id
列,虽然ID是众所周知的 - NHibernate将它作为参数传递给第一个插入语句...
答案 0 :(得分:2)
如此接近,您需要设置Not.Inverse()
,如this answer所示。
mapping.HasMany(x => x.Columns)
.KeyColumn("table_id")
.Not.Inverse()
.Not.KeyNullable()
.Not.KeyUpdate()
.Cascade.AllDeleteOrphan();
我不认为将双向关系变为黑客,通常需要进行查询。
答案 1 :(得分:2)
您没有提到您正在使用的NHibernate版本 - 但我会注意到,根据this jira issue,这似乎已在版本3.2.0中得到修复。
如果您坚持使用另一个版本的NHibernate,我建议将关系设置为双向,因为在我看来,这是使用可空的FK的更好选择。