在C#事务中获取Oracle数据库子对象ID的实现方法咨询
解决Oracle事务中子对象ID无法获取的问题
你现在碰到的问题很明确:在同一个事务流程里,父DATA对象的ID能正常拿到,但插入子DATA对象后,没法获取它的自增ID,导致后续插入关联的DATA2数据时,没法给ALIAS_ID字段赋值。核心问题出在代码执行顺序上——你现在是先处理DATA2的插入逻辑,再把子对象添加到数据上下文,这时候子对象还没真正写入数据库,自然拿不到生成的ID。
下面给你具体的修复方案:
1. 调整代码执行顺序
你得先把子对象插入数据库并拿到它的ID,再去处理关联的DATA2数据。同时要确保你的数据上下文或者Add方法,能在插入后自动把数据库生成的ID回填到子对象的ID属性上。
修复后的完整代码示例
using (DatabaseContext lContext = new DemoDatabaseContext()) { try { // 手动开启事务(如果你的DatabaseContext没有自动开启事务的话) lContext.BeginTransaction(); foreach (var alias in pLstAlias) { DATA lAlias = new DATA(); lAlias.ID = alias.ID; lAlias.FIRST_NAME = alias.FIRST_NAME; lAlias.SECOND_NAME = alias.SECOND_NAME; lAlias.NAME_CONCAT = alias.GetConcatName(); lAlias.SYSTEM_NAME = alias.GetSystemName(lAlias.NAME_CONCAT); lAlias.Add(lContext); // 如果父对象也是自增生成ID,这里也需要执行SaveChanges来回填ID // lContext.SaveChanges(); if (alias.AKAList != null) { foreach (var aka in alias.AKAList) { // 补全new关键字,你原来的代码这里漏了 DATA lChildAlias = new DATA(); lChildAlias.PARENT_ID = lAlias.ID; lChildAlias.AKA__NAME = aka.FIRST_NAME; lChildAlias.NAME_CONCAT = aka.GetConcatName(); lChildAlias.SYSTEM_NAME = aka.GetSystemName(lChildAlias.NAME_CONCAT); // 第一步:先将子对象添加到上下文并执行数据库插入 lChildAlias.Add(lContext); // 关键操作:执行SaveChanges触发数据库插入,让ID自动回填 lContext.SaveChanges(); // 现在lChildAlias.ID已经有数据库生成的有效值了 List<DATA2> aliasList = StoreRecodsToObject(lChildAlias.SYSTEM_NAME); if (aliasList != null) { foreach (var item in aliasList) { DATA2 DataForAliases = new DATA2(); // 这里可以正常赋值子对象的ID了 DataForAliases.ALIAS_ID = lChildAlias.ID; DataForAliases.NAME = item.NAME; DataForAliases.Add(lContext); } // 批量提交DATA2的插入 lContext.SaveChanges(); } } } } // 提交整个事务,确保所有操作都生效 lContext.CommitTransaction(); return true; } catch (Exception ex) { lContext.Rollback(); // 建议在这里添加日志记录,方便排查问题 return false; } }
2. 确保ID回填的关键细节
如果你的DATA实体的ID是通过Oracle序列+触发器实现自增的,那还需要确保ID能正确回填:
- 如果你用的是自定义的
Add方法,可以在插入语句执行后,立即执行SELECT YOUR_SEQUENCE_NAME.CURRVAL FROM DUAL,把查询结果赋值给lChildAlias.ID - 如果用的是Entity Framework,给
ID字段加上[DatabaseGenerated(DatabaseGeneratedOption.Identity)]特性,同时配置EF识别对应的Oracle序列,这样EF会自动帮你完成ID回填
3. 事务的注意事项
- 所有操作必须在同一个事务范围内,这样才能保证要么全部成功提交,要么全部回滚,避免数据不一致
- 虽然可以批量调用
SaveChanges,但子对象必须先执行SaveChanges拿到ID,才能处理后续的关联数据插入
内容的提问来源于stack exchange,提问作者Abdul
相关产品推荐
相关产品推荐

