首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ExecuteNonQuery 回傳值完整解析:不只看 > 0 這麼簡單

     編輯:ASP.NET 基礎

回傳值定義 (MSDN)

SQL 命令類型 成功時回傳 失敗/無影響時
INSERT / UPDATE / DELETE 受影響的資料列數 (int >= 0) 0 (無符合條件列)
CREATE TABLE / DDL / SET 陳述式 -1 拋出 Exception
預存程序 (無 SET NOCOUNT ON) 受影響列數 0 或 -1
預存程序 (SET NOCOUNT ON) -1 -1

為什麼不能只寫 if (rows > 0)?

// 建立資料表
string ddl = "CREATE TABLE Demo (Id INT PRIMARY KEY)";
int result = cmd.ExecuteNonQuery(); // 成功回傳 -1,而非 1

if (result > 0) // 錯誤!會誤判為失敗
    Console.WriteLine("成功"); // 不會執行
else
    Console.WriteLine("失敗或無影響"); // 錯誤訊息

正確判斷模式

模式 A:DML (增刪改) → 檢查 > 0

int affected = cmd.ExecuteNonQuery();
if (affected > 0)
    // 確實有資料異動
else
    // 無資料符合條件 (WHERE 不匹配) 或嘗試插入重複鍵被忽略

模式 B:DDL / 結構變更 → 捕捉 Exception

try
{
    int result = cmd.ExecuteNonQuery(); // 成功通常 -1
    // 不檢查 result,沒拋出例外即代表成功
}
catch (SqlException ex) when (ex.Number == 2714) // 資料表已存在
{
    // 處理已存在情況
}
catch (Exception ex)
{
    // 記錄日誌、回滾、拋出
}

模式 C:預存程序 → 使用 OUTPUT 參數或 RETURN VALUE

var cmd = new SqlCommand("usp_UpdateStock", conn) { CommandType = CommandType.StoredProcedure };
cmd.Parameters.Add("@ProductId", SqlDbType.Int).Value = 100;
var retParam = cmd.Parameters.Add("@Result", SqlDbType.Int);
retParam.Direction = ParameterDirection.ReturnValue;

cmd.ExecuteNonQuery();
int spResult = (int)retParam.Value; // 由 SP 定義:0=成功, -1=庫存不足, -2=商品不存在
// 依 spResult 判斷業務邏輯

實務封裝建議:統一回傳結構

public class DbResult
{
    public bool Success { get; set; }
    public int AffectedRows { get; set; }
    public string Message { get; set; }
    public Exception Exception { get; set; }
}

public static DbResult ExecuteNonQuerySafe(string sql, params SqlParameter[] parameters)
{
    var result = new DbResult();
    try
    {
        using (var conn = new SqlConnection(ConnStr))
        using (var cmd = new SqlCommand(sql, conn))
        {
            if (parameters != null) cmd.Parameters.AddRange(parameters);
            conn.Open();
            result.AffectedRows = cmd.ExecuteNonQuery();
            result.Success = true;
        }
    }
    catch (Exception ex)
    {
        result.Success = false;
        result.Exception = ex;
        result.Message = ex.Message;
    }
    return result;
}

關鍵提醒

  1. 永遠包裹 try-catch:DDL、權限不足、死結、網路中斷皆會拋出例外。
  2. 預存程序加 SET NOCOUNT ON:避免干擾回傳值,改用 OUTPUT/RETURN VALUE 傳遞業務狀態。
  3. 異步版本:.NET 4.5+ 使用 ExecuteNonQueryAsync 配合 CancellationToken。
  4. 交易控制:多條 DML 需包在 SqlTransaction 中,統一 Commit/Rollback。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved