C# & SQL Server:UPDATE生效但SMO返回受影响行数为-1?
问题分析与解决方案
我明白你遇到的困扰了——明明UPDATE操作已经生效,用SMO执行带GO的脚本时,捕获到的受影响行数却总是-1。这其实和SMO处理多批SQL脚本的机制有关,咱们一步步拆解:
为什么会返回-1?
你执行的脚本包含三个由GO分隔的批处理:
SET QUOTED_IDENTIFIER ONSET ANSI_NULLS ONUPDATE 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
相关产品推荐
相关产品推荐

