You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# & SQL Server:UPDATE生效但SMO返回受影响行数为-1?

问题分析与解决方案

我明白你遇到的困扰了——明明UPDATE操作已经生效,用SMO执行带GO的脚本时,捕获到的受影响行数却总是-1。这其实和SMO处理多批SQL脚本的机制有关,咱们一步步拆解:

为什么会返回-1?

你执行的脚本包含三个由GO分隔的批处理:

  1. SET QUOTED_IDENTIFIER ON
  2. SET ANSI_NULLS ON
  3. UPDATE Program SET ENABLED = '1' WHERE ...

SMO在执行这类多批脚本时,ExecuteNonQuery默认会返回最后一个批处理的执行结果。但前两个SET语句属于配置类命令,本身不会返回受影响行数,执行后会返回-1。如果你的代码没有正确区分各批的结果,就可能误拿到前两个批的返回值,最终得到-1的结果。

两种解决办法

方法1:将配置语句转为连接属性设置(推荐)

既然QUOTED_IDENTIFIER和ANSI_NULLS是连接级别的配置,完全可以通过SMO的连接上下文直接设置,不用写在SQL脚本里。这样脚本只保留UPDATE语句,就能准确捕获受影响行数:

// 假设db是你的SMO Database实例
db.ConnectionContext.QuotedIdentifier = true;
db.ConnectionContext.AnsiNulls = true;

// 执行单独的UPDATE语句
string updateSql = "UPDATE Program SET ENABLED = '1' WHERE Program_ID = '64' AND Program_Name = 'DoesSomething'";
int numberOfRows = db.ConnectionContext.ExecuteNonQuery(updateSql);

这种方式既简洁,又能避免多批脚本带来的结果捕获问题。

方法2:拆分多批脚本,逐个执行并收集结果

如果你必须保留原脚本的结构,可以用SMO的ParseBatch方法把脚本拆分成单个批处理,然后逐个执行,只累加DML语句的受影响行数:

string fullScript = @"SET QUOTED_IDENTIFIER ON 
GO 
SET ANSI_NULLS ON 
GO 
UPDATE Program SET ENABLED = '1' WHERE Program_ID = '64' AND Program_Name = 'DoesSomething'";

// 拆分脚本为独立的批处理
IEnumerable<string> batches = db.ConnectionContext.ParseBatch(fullScript);
int totalAffectedRows = 0;

foreach (string batch in batches)
{
    int affected = db.ConnectionContext.ExecuteNonQuery(batch);
    // 忽略配置类语句返回的-1,只累加有效行数
    if (affected != -1)
    {
        totalAffectedRows += affected;
    }
}

// totalAffectedRows就是UPDATE实际影响的行数

这样就能准确拿到UPDATE操作的受影响行数啦。

内容的提问来源于stack exchange,提问作者shindigwagon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:16:47