VB.NET中DBConcurrencyException处理异常:主键值为Null问题求助
VB.NET中DBConcurrencyException异常行主键为Null的问题分析与解决建议
可能的原因
异常行状态导致主键值丢失
当触发并发冲突时,DBEX.Row可能处于Deleted状态,此时DataRow的Current版本列值会被清空,但Original版本仍保留行修改前的原始数据。如果直接取Item("RecID"),默认读取的是Current版本,自然会得到Null。
另外,你关闭了关系的子约束(createConstraints=False),DataSet不会强制维护行的完整性校验,行状态变更时主键值的逻辑维护可能出现疏漏,间接导致值丢失。DataAdapter配置缺失
如果POs表的DataTable没有明确设置PrimaryKey属性,DataSet无法准确识别主键列,在并发异常发生时,可能无法正确保留主键值。此外,若UpdateCommand的WHERE子句没有正确包含原始主键值用于并发校验,也可能导致异常行的主键值无法被正确追踪。
解决建议
- 从原始版本获取主键值
捕获异常后,先判断行状态,从Original版本提取主键:
Dim recId As Object If DBEX.Row.RowState = DataRowState.Deleted Then recId = DBEX.Row.Item("RecID", DataRowVersion.Original) Else recId = DBEX.Row.Item("RecID") End If Dim TmpTbl As DataTable = GetDBRow("POs", "RecID", recId)
Deleted状态的行只有Original版本保留了完整的原始数据,这样就能拿到正确的主键值。
- 明确设置DataTable主键
确保POs表的DataTable正确配置主键:
DS.Tables("POs").PrimaryKey = New DataColumn() {DS.Tables("POs").Columns("RecID")}
这会让DataSet明确识别主键列,在处理行状态变更和并发冲突时更好地维护数据完整性。
- 优化关系约束设置
如果业务逻辑允许,将关系的createConstraints参数改为True,启用引用完整性约束:
DS.Relations.Add("RPO", DS.Tables("Jobs").Columns("ID"), DS.Tables("POs").Columns("JobID"), True)
启用约束后,DataSet会自动维护父子行的关联状态,减少主键值意外丢失的概率。如果必须关闭约束,需手动处理行状态变更时的主键值同步逻辑。
- 从UpdateCommand参数提取主键
如果你的UpdateCommand使用了原始主键作为并发校验条件(比如包含@Original_RecID参数),可以直接从参数中获取值:
Dim recIdParam As SqlParameter = CType(PODataAdapter.UpdateCommand.Parameters("@Original_RecID"), SqlParameter) Dim TmpTbl As DataTable = GetDBRow("POs", "RecID", recIdParam.Value)
这是一种兜底方案,确保能拿到用于并发校验的原始主键值。
内容的提问来源于stack exchange,提问作者Larry Stinson
相关产品推荐
相关产品推荐

