我在下表中添加了装饰器DatabaseGenerated
,如下所示:
public class Reference
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public decimal ReferenceId { get; set; }
public string AddressType { get; set; }
public string RefferenceType { get; set; }
public string RefferenceValue { get; set; }
[ForeignKey("Shipment")]
public decimal? TrackingNumber { get; set; }
public Shipment Shipment { get; set; }
}
我最近向上迁移到oracle 19c DB的是:
public override void Up()
{
DropPrimaryKey("SALOGSEARCH.References");
AlterColumn("SALOGSEARCH.References", "ReferenceId", c => c.Decimal(nullable: false, precision: 20, scale: 0, identity: true));
AddPrimaryKey("SALOGSEARCH.References", "ReferenceId");
}
然而,当我在添加后执行上下文保存时:
using (var context = new DbContext())
{
context.Reference.Add(shipperReference);
context.SaveChanges();
}
我得到一个异常
ORA-01400:无法插入空
我假设标记DatabaseGeneratedOption.Identity
将在Oracle数据库中生成一个序列,并在next或something上从默认值调用它。但事实并非如此。
我现在必须手动为每列创建一个触发器和序列吗?
如果是这样的话,那么如果我必须自己干预数据库,那么代码首先有什么意义呢。
我不确定这是否有任何影响,但我正在这样调整OnModelCreating
:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("SALOGSEARCH");
modelBuilder.Properties<string>().Configure(s => s.HasMaxLength(400).HasColumnType("Varchar2"));
modelBuilder.Properties<decimal>().Configure(s => s.HasPrecision(20, 0).HasColumnType("Number"));
}
任何从c端解决这个问题的指针都将不胜感激。
第1版:在本教程之后,我意识到模型类(表(的Id需要是一个int,在oracle术语中是数字(10,0(,以便在DB端自动创建所需的序列(作为调用nextVal的列默认值(。
然而,从向上迁移的情况来看,似乎没有任何迹象表明这种序列的产生,所以它只是让我相信,这种产生发生在我知识领域之外更深的地方。
DatabaseGeneratedOption.Identity
需要一个序列或一个标识列。
自12c版本起,就支持标识列,触发器和序列都不引用标识列。它们由Oracle内部处理。如果你得到一个错误
ORA-01400:无法插入空
这可能是因为在没有显式命名列的情况下进行插入,或者因为使用了错误的IDENTITY类型,或者因为没有序列。
IDENTITY
列有这些选项
GENERATED ALWAYS
:Oracle始终为标识列生成一个值。尝试在标识列中插入值将导致错误GENERATED BY DEFAULT
:如果您不提供值,Oracle将为标识列生成一个值。如果您提供了一个值,Oracle会将该值插入标识列中。对于此选项,如果在标识列中插入NULL值,Oracle将发出错误GENERATED BY DEFAULT ON NULL
:Oracle会为标识列生成一个值,如果您提供了NULL值或根本没有值
示例
SQL> create table t ( c1 number generated by default as identity ( start with 1 increment by 1 ) , c2 number ) ;
Table created.
SQL> insert into t ( c2 ) values ( 1 ) ;
1 row created.
SQL> select * from t ;
C1 C2
---------- ----------
1 1
SQL> insert into t ( c1 , c2 ) values ( null , 1 ) ;
insert into t ( c1 , c2 ) values ( null , 1 )
*
第1行错误:
ORA-01400:无法将NULL插入("MY_SCHEMA"."T"."C1"(
但是我可以插入并明确引用IDENTITY
SQL> insert into t ( c1, c2 ) values ( 2, 2 ) ;
1 row created.
SQL> select * from t ;
C1 C2
---------- ----------
1 1
2 2
SQL> insert into t ( c2 ) values ( 3 ) ;
1 row created.
SQL> select * from t ;
C1 C2
---------- ----------
1 1
2 2
2 3
在你的情况下,我会使用GENERATED BY DEFAULT ON NULL
:
SQL> create table t ( c1 number generated by default on null as identity ( start with
1 increment by 1 ) , c2 number ) ;
Table created.
SQL> insert into t values ( null , 1 ) ;
1 row created.
SQL> select * from t ;
C1 C2
---------- ----------
1 1