为何通过C#调用存储过程无法更新SQL Server数据表值?
问题:C#执行存储过程无数据变更,SSMS执行正常
通过C#调用存储过程时,数据表ac00中的值没有变化;但在SQL Server Management Studio(SSMS)中直接执行该存储过程,却能正常更新数据。
C# 调用代码
DatabaseLibrary.ParametersClear(); DatabaseLibrary.command.Parameters.Add(new SqlParameter("@guid", SqlDbType.UniqueIdentifier)).Value = formGuid; DatabaseLibrary.command.Parameters.Add(new SqlParameter("@val", SqlDbType.Float)).Value = (Sumsrc.Net * Convert.ToDouble(ParityTxt.Text)); DatabaseLibrary.command.Parameters.Add(new SqlParameter("@in", SqlDbType.Bit)).Value = input ? 1 : 0; DatabaseLibrary.command.Parameters.Add(new SqlParameter("@operation", SqlDbType.Bit)).Value = 1; DatabaseLibrary.ExecuteStoredProcedure(StoredProcedure.AccountUpdate);
存储过程代码
CREATE PROCEDURE [dbo].[AccountUpdate] @guid uniqueidentifier, @val float, @in bit, -- 1 or 0 @operation bit -- 1 or 0 AS BEGIN DECLARE @oldVal float IF (@in > 0) BEGIN IF (@operation > 0) BEGIN SET @oldVal = (SELECT ISNULL(Debit, 0) FROM ac00 WHERE GUID = @guid) UPDATE ac00 SET [Debit] = (@oldVal + @val) WHERE GUID = @guid END ELSE BEGIN SET @oldVal = (SELECT ISNULL(Debit, 0) FROM ac00 WHERE guid = @guid) UPDATE ac00 SET [Debit] = (@oldVal - @val) WHERE GUID = @guid END END ELSE BEGIN IF (@operation > 0) BEGIN SET @oldVal = (SELECT ISNULL(Credit, 0) FROM ac00 WHERE GUID = @guid) UPDATE ac00 SET [Credit] = (@oldVal + @val) WHERE GUID = @guid END ELSE BEGIN SET @oldVal = (SELECT ISNULL(Credit, 0) FROM ac00 WHERE GUID = @guid) UPDATE ac00 SET [Credit] = (@oldVal - @val) WHERE GUID = @guid END END END
排查与解决方法
- 检查事务提交:SSMS默认自动提交事务,但你的
DatabaseLibrary可能开启了事务却未显式提交。查看ExecuteStoredProcedure方法内部逻辑,确保执行完成后调用了事务的Commit()方法。 - 验证参数有效性:
- 在C#代码中打印
formGuid、计算后的@val、input的实际值,对比SSMS执行时传入的参数是否完全一致。 - 确认
formGuid是有效的Guid,没有空值或格式错误,避免WHERE GUID = @guid匹配不到数据行。 - 注意
float类型精度问题,C#计算后的数值可能和SSMS中输入的存在微小差异,导致更新效果不明显。
- 在C#代码中打印
- 优化存储过程逻辑:当前先查询再更新的写法存在并发风险,且冗余代码多,可简化为单条UPDATE语句,避免查询与更新之间的不一致:
CREATE PROCEDURE [dbo].[AccountUpdate] @guid uniqueidentifier, @val float, @in bit, @operation bit AS BEGIN IF (@in = 1) BEGIN UPDATE ac00 SET Debit = ISNULL(Debit, 0) + CASE WHEN @operation = 1 THEN @val ELSE -@val END WHERE GUID = @guid END ELSE BEGIN UPDATE ac00 SET Credit = ISNULL(Credit, 0) + CASE WHEN @operation = 1 THEN @val ELSE -@val END WHERE GUID = @guid END END - 跟踪SQL执行:用SQL Server Profiler或扩展事件,捕获C#调用存储过程时的实际执行语句和参数,和SSMS的执行记录对比,定位差异点。
内容的提问来源于stack exchange,提问作者Davied
相关产品推荐
相关产品推荐

