如何从实体框架代码优先的方法自动增加oracle表



我在下表中添加了装饰器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

最新更新