You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Entity Framework Add()写入Oracle数据库时触发虚拟列插入禁用错误

问题描述

我有一个Oracle数据库,包含多张表(其中3张表的ID列配置为ALWAYS GENERATED IDENTITY),需连接至Windows Form程序。

BREAKDOWN表结构

CREATE TABLE "BREAKDOWN" 
   ("EQUIPMENTID" NCHAR(8) NOT NULL ENABLE, 
    "FROMTIME" TIMESTAMP (4), 
    "TOTIME" TIMESTAMP (4), 
    "WORKORDER" NUMBER(10,0) NOT NULL ENABLE, 
    "BDNREASON" NCHAR(10), 
    "BDNTIME" INTERVAL DAY (2) TO SECOND (6) GENERATED ALWAYS AS (("TOTIME"-"FROMTIME")DAY(9) TO SECOND(4)) VIRTUAL , 
    "BREAKDOWNID" NUMBER(10,0) GENERATED ALWAYS AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER  NOCYCLE  NOT NULL ENABLE, 
     CONSTRAINT "BREAKDOWN_PK" PRIMARY KEY ("BREAKDOWNID") )

BREAKDOWN实体类

public partial class BREAKDOWN
{
    public string EQUIPMENTID { get; set; }
    public Nullable<System.DateTime> FROMTIME { get; set; }
    public Nullable<System.DateTime> TOTIME { get; set; }
    public int WORKORDER { get; set; }
    public string BDNREASON { get; set; }
    public int BREAKDOWNID { get; set; }
    public Nullable<decimal> BDNTIME { get; set; }

    public virtual EQUIPMENT EQUIPMENT { get; set; }
    public virtual WORKORDER WORKORDER1 { get; set; }
}

WORKORDER表结构

CREATE TABLE "WORKORDER" 
(
    "WORKORDERTYPEID" NCHAR(3) NOT NULL ENABLE, 
    "WORKORDEREQUIPMENTID" NCHAR(8) NOT NULL ENABLE, 
    "WORKORDERREGISTERATIONDATE" TIMESTAMP (3) NOT NULL ENABLE, 
    "WORKORDERID" NUMBER(10,0) GENERATED ALWAYS AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 NOCACHE  NOORDER  NOCYCLE  NOT NULL ENABLE, 
     CONSTRAINT "WORKORDER_PK" PRIMARY KEY ("WORKORDERID")
)

WORKORDER实体类

public partial class WORKORDER
{
    public WORKORDER()
    {
        this.BREAKDOWNs = new HashSet<BREAKDOWN>();
    }
    public string WORKORDERTYPEID { get; set; }
    public string WORKORDEREQUIPMENTID { get; set; }
    public System.DateTime WORKORDERREGISTERATIONDATE { get; set; }
    public int WORKORDERID { get; set; }
}

错误现象

使用Oracle SQL Developer手动插入数据时,三张表的IDENTITY功能均正常。但通过Windows Form使用Entity Framework的Add()方法插入数据时,仅BREAKDOWN表触发如下错误:

System.Data.Entity.Infrastructure.DbUpdateException: 'An error occurred while updating the entries. See the inner exception for details.' UpdateException: An error occurred while updating the entries. See the inner exception for details. OracleException: ORA-54013: INSERT operation disallowed on virtual columns ORA-06512: at line 4

插入代码

BREAKDOWN插入代码(报错)

BREAKDOWN newBDN = new BREAKDOWN();
newBDN.WORKORDER = workOrder.WORKORDERID;
newBDN.EQUIPMENTID = workOrder.WORKORDEREQUIPMENTID;
newBDN.FROMTIME = bdnFromDateTimePicker.Value;
home.dbContext.BREAKDOWNs.Add(newBDN);
home.dbContext.SaveChanges();

WORKORDER插入代码(正常)

WORKORDER newWorkOrder= new WORKORDER ();
newWorkOrder.EQUIPMENT = (EQUIPMENT) equipmentBindingSource.DataSource;
newWorkOrder.WORKORDERREGISTERATIONDATE = regsiterationDatePicker.Value;
newWorkOrder.WORKORDERTYPE = (WORKORDERTYPE)workTypeTextBox.SelectedItem;
home.dbContext.WORKORDERs.Add(newWorkOrder);
home.dbContext.SaveChanges();

已确认:

  • 相关列均为带对应ISEQ的IDENTITY列;
  • 数据库表与实体类的所有列数据类型一致;
  • Oracle可正确计算IDENTITY属性(通过Oracle SQL Developer手动插入验证)。

解决方案

错误根源是EF尝试向Oracle的**虚拟列(BDNTIME)**执行插入操作,而Oracle禁止对虚拟列进行INSERT/UPDATE操作。WORKORDER表没有虚拟列,所以插入正常。

方法1:使用DataAnnotations标记虚拟列为计算列

修改BREAKDOWN实体类的BDNTIME属性,添加[DatabaseGenerated(DatabaseGeneratedOption.Computed)]特性,告诉EF该列由数据库生成,不需要在插入/更新时处理:

using System.ComponentModel.DataAnnotations.Schema; // 需要引入此命名空间

public partial class BREAKDOWN
{
    // ... 其他属性 ...
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public Nullable<decimal> BDNTIME { get; set; }
    // ... 导航属性 ...
}

方法2:使用Fluent API配置

如果不想修改实体类,可以在DbContext的OnModelCreating方法中配置该属性:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<BREAKDOWN>()
        .Property(b => b.BDNTIME)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
    
    // ... 其他实体配置 ...
}

额外检查

同时确认BREAKDOWN的IDENTITY列(BREAKDOWNID)也正确配置为数据库生成:

// DataAnnotations方式
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int BREAKDOWNID { get; set; }

// 或Fluent API方式
modelBuilder.Entity<BREAKDOWN>()
    .Property(b => b.BREAKDOWNID)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

完成配置后,EF会自动跳过对BDNTIME列的插入操作,仅处理用户指定的列,即可解决ORA-54013错误。


内容的提问来源于stack exchange,提问作者Mohamed Reyad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 23:27:46