4

我正在尝试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 不可用] ---> Oracle.DataAccess.Client.Orac leException:ORA-01400:无法将 NULL 插入(“MYSCHEMA”。“DATA_EXPORT_COLUMNS”。” TABLE_ID")

现在,我阅读了很多关于这个主题的帖子,普遍接受的解决方案似乎是使引用双向,即添加一个Table属性DataExportColumn并设置它。
另一个“hack”是使外键列可以为空。那不是我想要的。我希望 NHibernate 直接在 INSERT 语句中插入 ID。
根据日志文件,NHibernate 在执行 INSERT 语句时肯定知道 ID:

NHibernate:从双
NHibernate 中选择 SQ_DATA_EXPORT_TABLES_ID.nextval:批处理命令:
命令 0:INSERT INTO data_export_tables (NAME, data_export_tables_id) VALUES (:p0, :p1);:p0 = 'table_name' [Type: String (0)], :p1 = 93 [类型:Int32 (0)]

NHibernate:批处理命令:
命令 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 )]

如您所见,NHibernate 只是省略了该table_id列,尽管 ID 是众所周知的 - NHibernate 将其作为参数传递给第一个插入语句......

4

2 回答 2

2

您没有提及您使用的是哪个版本的 NHibernate - 但我会注意到,根据这个 jira 问题,这似乎已在 3.2.0 版本中得到修复。

如果您坚持使用另一个版本的 NHibernate,我建议您将关系设为双向,因为在我看来,它是使用可为空的 FK 的更好选择。

于 2013-01-25T17:57:55.263 回答
2

如此接近,您需要Not.Inverse()按照此答案进行设置。

mapping.HasMany(x => x.Columns)
       .KeyColumn("table_id")
       .Not.Inverse()
       .Not.KeyNullable()
       .Not.KeyUpdate()
       .Cascade.AllDeleteOrphan();

我不认为将关系设为双向是一种黑客行为,并且通常需要进行查询。

于 2013-01-21T18:28:23.260 回答