C#执行Update查询时使用AddWithValue保留字段原有值的方法
问题原因
你当前的写法在入参为null时给参数赋值DBNull.Value,执行UPDATE时会直接将对应数据库字段覆盖为NULL,自然无法保留原有值。
实现方案
根据你的业务场景二选一即可:
方案1:SQL层做空值判断(代码改动最小,适合字段较少的场景)
直接修改UPDATE语句的赋值逻辑,通过SQL Server内置的ISNULL函数实现:传入参数为NULL时,直接使用字段自身的原有值赋值,不需要修改你原有的参数判断逻辑。
SqlCommand AddToFarms = new SqlCommand("Update Farms set " + "ProductiveTreesNo=ISNULL(@ProductiveTreesNo, ProductiveTreesNo)," + "MainCropsType=ISNULL(@MainCropsType, MainCropsType)" + " where OBJECTID =@OBJECTID", connection2); // 可以用空合并运算符简化原有if判断,效果完全一致 AddToFarms.Parameters.AddWithValue("@ProductiveTreesNo", item.ProductiveTreesNo ?? (object)DBNull.Value); AddToFarms.Parameters.AddWithValue("@MainCropsType", item.MainCropsType ?? (object)DBNull.Value); AddToFarms.Parameters.AddWithValue("@OBJECTID", item.OBJECTID);
该方案不需要动态拼接SQL,代码改动量极小,注意如果业务存在「主动把字段更新为NULL」的需求,不要用这个方案,会导致主动置空的逻辑失效。
方案2:动态拼接更新字段(性能最优,适合字段多、更新频繁的场景)
拼接SQL的SET子句时,只加入入参不为null的字段,对应参数也仅添加需要更新的字段,从根源上跳过null字段的更新,数据库执行效率更高。
List<string> setPart = new List<string>(); List<SqlParameter> sqlParams = new List<SqlParameter>(); if (item.ProductiveTreesNo != null) { setPart.Add("ProductiveTreesNo=@ProductiveTreesNo"); sqlParams.Add(new SqlParameter("@ProductiveTreesNo", item.ProductiveTreesNo)); } if (item.MainCropsType != null) { setPart.Add("MainCropsType=@MainCropsType"); sqlParams.Add(new SqlParameter("@MainCropsType", item.MainCropsType)); } sqlParams.Add(new SqlParameter("@OBJECTID", item.OBJECTID)); // 没有需要更新的字段时直接返回,避免执行无效SQL if (setPart.Count == 0) return; SqlCommand AddToFarms = new SqlCommand( $"Update Farms set {string.Join(",", setPart)} where OBJECTID =@OBJECTID", connection2 ); AddToFarms.Parameters.AddRange(sqlParams.ToArray());
该方案不会产生冗余的赋值逻辑,不会触发无意义的字段更新,也可以通过额外的标识位扩展支持「主动更新字段为NULL」的需求,是生产环境更推荐的写法。
补充建议
- 生产环境尽量减少
AddWithValue的使用,该方法自动推断参数类型的逻辑容易产生类型不匹配、隐式转换、执行计划缓存失效的问题,推荐显式指定参数的SqlDbType和对应长度。 - 如果后续业务需要区分「入参为null不更新」和「入参为null要把字段置空」两种逻辑,不要在入参实体上用null做判断标识,单独加对应字段的更新控制标记即可。
内容的提问来源于stack exchange,提问作者Noha
相关产品推荐
相关产品推荐

