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

EF Core使用RowVersion遇InvalidCastException,Oracle替代方案咨询

Oracle 下替代 EF Core [Timestamp](RowVersion)的可行方案

Oracle 并不支持 Entity Framework 中用于乐观并发的 [Timestamp] 特性(对应 SQL Server 的 RowVersion 类型),你遇到的 InvalidCastException: Unable to cast object of type 'System.DBNull' to type 'System.Byte[]' 错误,本质是现有数据中该 Raw 类型字段为 NULL,EF 无法将其转换为 byte[] 类型。以下是几种成熟的替代方案:

方案一:时间戳字段 + Oracle 触发器(推荐)

这是最常用的替代方式,利用 Oracle 的时间戳和触发器自动维护版本:

  1. 修改实体类:移除 [Timestamp] 属性,添加时间戳字段
public class Order
{
    // 其他字段...
    public DateTime LastModified { get; set; }
}
  1. 修改数据库表:添加对应字段,设置默认值为当前系统时间
ALTER TABLE ORDERS ADD LAST_MODIFIED TIMESTAMP(6) DEFAULT SYSTIMESTAMP;
  1. 创建触发器:确保每次更新时自动更新时间戳
CREATE OR REPLACE TRIGGER TRG_ORDERS_LAST_MODIFIED
BEFORE UPDATE ON ORDERS
FOR EACH ROW
BEGIN
    :NEW.LAST_MODIFIED := SYSTIMESTAMP;
END;
/
  1. EF 配置并发检查:在 DbContext 的 OnModelCreating 中标记该字段为并发令牌
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Order>()
        .Property(o => o.LastModified)
        .IsConcurrencyToken();
}

后续更新时,EF 会自动对比 LastModified 值,若不一致则抛出并发冲突异常。

方案二:自增数字版本号 + 触发器

如果对时间戳精度有顾虑,或者更倾向于数字版本管理,可以用自增版本号:

  1. 修改实体类:添加整数类型的版本字段
public class Order
{
    // 其他字段...
    public int Version { get; set; }
}
  1. 修改数据库表:添加版本字段,默认值设为 1
ALTER TABLE ORDERS ADD VERSION NUMBER(10, 0) DEFAULT 1;
  1. 创建触发器:每次更新时将版本号加 1
CREATE OR REPLACE TRIGGER TRG_ORDERS_VERSION
BEFORE UPDATE ON ORDERS
FOR EACH ROW
BEGIN
    :NEW.VERSION := :OLD.VERSION + 1;
END;
/
  1. EF 配置并发检查:同样标记为并发令牌
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Order>()
        .Property(o => o.Version)
        .IsConcurrencyToken();
}

方案三:手动维护版本字段(不推荐)

如果不想用触发器,可以在业务逻辑中手动更新版本值,但这种方式容易遗漏,可靠性较低:

  • 实体类添加时间戳或数字版本字段
  • 每次执行更新操作时,手动将版本字段设为当前时间或自增后的值
  • EF 中同样配置 IsConcurrencyToken()

临时解决当前的 DBNull 错误

如果暂时不想替换字段类型,可以先批量更新现有数据的 Raw 字段,给所有 NULL 值设置一个默认值:

UPDATE ORDERS SET VERSION = UTL_RAW.CAST_TO_RAW('0') WHERE VERSION IS NULL;

但这只是临时方案,长期来看还是建议换成上述两种触发器方案,更符合 Oracle 的生态和 EF 的并发检查逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 17:41:07