使用EntityFrameworkCore向Oracle批量插入时的序列重复键问题
解决EF Core向Oracle批量插入时HiLo主键重复问题
问题原因
你遇到的重复键问题核心是HiLo算法的块大小与分块插入量不匹配,导致EF Core无法正确从序列获取后续ID范围;或是序列配置、DbContext生命周期异常,使得第二次插入时重新从初始序列值生成ID。
HiLo默认块大小为1000,但你的分块插入是10000条,单次插入需要多次向Oracle序列请求高值,若序列配置或EF Core的块缓存逻辑出现异常,就会引发后续插入的ID范围重复。
可行解决方案
1. 显式指定HiLo块大小匹配分块插入量
修改实体配置,将HiLo块大小设置为每次插入的分块大小(10000),这样单次插入只需从序列获取一次高值,生成足够覆盖分块的ID范围,避免多次请求序列带来的异常:
builder.Property(x => x.Id).HasColumnName("GUID") .ValueGeneratedOnAdd() .UseHiLo("SEQ", "SCHEMA", 10000); // 第三个参数指定块大小为10000
2. 检查Oracle序列配置
确保序列SEQ的定义符合要求:
- 序列增量为1(
INCREMENT BY 1) - 无手动重置或错误的缓存设置
- EF Core具备执行
SELECT SEQ.NEXTVAL FROM DUAL的权限
可通过以下SQL查看序列状态:
SELECT sequence_name, increment_by, last_number FROM user_sequences WHERE sequence_name = 'SEQ';
3. 确保DbContext生命周期合理
如果BulkInsert每次调用都创建新的DbContext实例,需确认每个实例都能正确连接数据库并获取最新序列值。若使用依赖注入,Scoped生命周期的DbContext在同一请求内复用,可自动管理HiLo块的续接;若手动创建DbContext,需确保每次使用后正确释放。
4. 验证ID生成逻辑
插入前检查实体的Id是否被手动赋值(即便配置了ValueGeneratedOnAdd(),手动设置Id会覆盖自动生成逻辑),确保所有待插入实体的Id为默认值(0或null),由EF Core负责生成。
内容的提问来源于stack exchange,提问作者Yılmaz Buhar
相关产品推荐
相关产品推荐

