Begin Transaction Rollback:多Insert/Update事务异常回滚范围及重复键报错咨询
问题解答
异常发生时的回滚范围
在你提供的代码逻辑中,所有未提交的操作会被全部回滚,不会只回滚出错的单条语句。原因如下:
- 代码通过
conn.BeginTransaction()开启了一个数据库事务,所有后续的SQL操作都属于这个事务的范围。 - 不管
strQueryBuild中拼接了多少条INSERT/UPDATE语句,只要ExecuteNonQuery执行过程中任何一条语句抛出异常(比如重复键冲突),整个执行会中断并进入catch块,调用tra.Rollback()会撤销事务内的所有操作,数据库状态回到事务开启前的样子。
关于重复键冲突(duplicate key violation)错误
你再次执行时遇到这个错误,是因为你要插入的数据中,主键或唯一约束字段的值和数据库中已存在的记录重复了。需要注意:
- 第一次执行时事务回滚,意味着之前的操作没有被持久化到数据库,但如果第二次执行的仍然是包含重复键的相同数据,自然会触发PostgreSQL的唯一约束校验,抛出该错误。
- 解决思路可以是:
- 插入前先查询数据库,判断该键是否已存在,避免重复插入
- 使用PostgreSQL的
ON CONFLICT语法,在插入遇到冲突时执行更新或忽略操作(比如INSERT INTO sales(...) VALUES(...) ON CONFLICT (id) DO NOTHING)
你的代码片段
using (var conn = new NpgsqlConnection(connstr)) { conn.Open(); var tra = conn.BeginTransaction(); try { NpgsqlCommand cmd = new NpgsqlCommand(); cmd.Connection = conn; cmd.CommandType = CommandType.Text; cmd.CommandTimeout = 0; cmd.CommandText = strQueryBuild.ToString(); RowsAffected = cmd.ExecuteNonQuery(); tra.Commit(); commitstatus = true; } catch (Exception ex) { commitstatus = false; AppHelper.ErrrorLog(ex, "UploadFileData-Error1"); RowsAffected = -1; tra.Rollback(); } }
内容的提问来源于stack exchange,提问作者Manjay
相关产品推荐
相关产品推荐

