为这种情况找到合适的映射咒语有点困难。
我有一个Oracle数据库,其中包含一系列包含如下定义的标识列的表:
"ID" NUMBER GENERATED ALWAYS AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 NOCACHE NOORDER NOCYCLE NOT NULL ENABLE
我的模型定义如下:
public class MyModel
{
public virtual decimal Id { get; set; }
public virtual string SomeProperty { get; set; }
}
像这样映射:
public class MyModelMap : ClassMapping<MyModel> {
public MyModelMap() {
Schema("OWNER");
Lazy(true);
Id(x => x.Id, map =>
{
map.Generator(Generators.SequenceIdentity, gmap => gmap.Params(new {sequence = "MySequenceName" }));
});
Property(x => x.SomeProperty, map => { map.NotNullable(true); map.Length(2); });
}
}
当我尝试用这种方式映射`Session.Save(myModelObject)'时,NHibernate会生成这个:
INSERT INTO OWNER.MyModel
(Id,
SomeProperty)
VALUES (OWNER.MySequenceName.nextval,
'AA' /* :p0 */)
returning Id into :nhIdOutParam
数据库响应:
错误:ORA-32795:无法插入生成的始终标识列无法执行命令:INSERT INTO ...
这就像我已经能够通过NH在这些表中插入新记录一样接近。我也试过了其他几台发电机。例如,使用
Generators.Sequence
导致像这样的INSERT ......
INSERT INTO OWNER.MyModel
(SomeProperty, Id)
VALUES ('AA' /* :p0 */, 50 /* :p1 */)
returning Id into :nhIdOutParam
...与数据库产生相同的错误(与Native,Sequence和EnhancedSequence Generators相同)。 Id每次都包含在INSERT中,要么具有特定值(按序列),要么对序列进行.nextval
调用,当然,数据库告诉我我不允许这样做那。我无法找到一种方法来阻止NH尝试在Oracle中设置Id,从而让DB在INSERT上设置它。我在SQL Server中有类似的映射表,使用Identity Generator - NH不会尝试为这些表传递Id并且它们工作正常。
那么,我如何告诉NHibernate不要在它生成的INSERT中包含Id列?
我尝试设置map.Access(Accessor.ReadOnly);
以防止这种情况发生,但是,除了SequenceIdentity Generator之外,导致NH无法通过以下投诉产生INSERT:
{“MyModel实例的标识符从54更改为0”}
(我的猜测 - NH正如预期的那样从数据库序列中获取下一个Id,但显然对于具有默认值0的实体Id存在问题。它指责我改变它,但我感觉他们是无辜的。)
我可以继续列出我尝试过的所有内容,但希望我已经为比我更聪明的人提供了足够的信息来建立一些建议。提前谢谢!
答案 0 :(得分:0)
NHibernate目前不support identity columns with Oracle。
改为使用序列。
否则,尝试从Oracle12cDialect
派生,覆盖SupportsIdentityColumns
以返回true
,覆盖适合Oracle的其他身份相关属性/方法,配置应用程序以使用新方言,地图您使用Identity
生成的ID,并对其进行测试。
有关详细信息,请参阅Dialect
标识区域。如果您能够实施身份支持,欢迎PR
在Hibernate方面,它看起来已实现,如果这可以帮助您使用NHibernate实现它,请参阅here。