【问题标题】:ExecuteNonQuery Returns -1 when the code succeedsExecuteNonQuery 代码成功时返回 -1
【发布时间】:2019-03-24 22:52:39
【问题描述】:

我用 C# 编写了一个工具,它允许我的经理在每个月底运行一组 SQL 命令。 SQL 命令存储在数据库中,因此我可以在需求变化时轻松维护它。根据前一个命令的成功与否,每个后续命令可能会或可能不会被允许运行。

实际上存储在我的数据库中的命令只是一个 SQL 命令,它调用所有复杂内容所在的存储过程。

我正在使用命令 C#ExecuteNonQuery(),如果它失败,通常会返回 -1,如果成功则返回其他值(到目前为止一切都很好)。多年来一直如此。

现在是维护位。

我所有的存储过程之前都在更新我的数据库中的数据。我现在需要添加一个存储过程来检查数据库中是否已经存在某些内容。如果它不存在或完全失败,如果数据确实存在,我想返回 -1 或其他值。

我已尝试转为 SET NOCOUNT OFF,但这并没有帮助,我认为我已经缩小了范围,因为我的最新程序没有更新任何内容,因此 ExecuteNonQuery 认为这是失败的。

我已经在 Management Studio 中运行了这些命令,它们按预期报告了成功。当前命令甚至在消息选项卡中返回“1 行影响”。

这是存储过程代码,因此您可以看到我到目前为止所做的尝试。 我试图避免修改我的 C# 程序,以便根据调用的 SQL 类型使用不同的命令。

有人有想法吗?

USE [Billing]
GO
/****** Object:  StoredProcedure [dbo].[Billing_Test_Uncharged_Entries]    
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- 
ALTER PROCEDURE [dbo].[Billing_Test_Uncharged_Bing_Entries] 
    -- Add the parameters for the stored procedure here
AS

DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;

BEGIN TRY
    --SET NOCOUNT ON;
    Set NOCOUNT OFF;

    -- Insert statements for procedure here
    --SELECT <@Param1, sysname, @p1>, <@Param2, sysname, @p2>
    If Not Exists
    (
        SELECT [lSundriesID]
        FROM [Strata].[dbo].[vjrSundries]
        where 
        lFeeCodeID = '77' And
        -- lFeeCodeID = '999' And  --(Use this line to force an error during testing)
        lMonthfeeApplies is null
    )
    Begin
        --print 'Nothing to see here'
        --Return -1

        SELECT 
            @ErrorMessage = 'No FeeCodeID=77 Items found, Has the Bing EP Mailroom import process been run in Sundries',
            @ErrorSeverity = 11,
            @ErrorState = 1;

            RAISERROR (
                @ErrorMessage,  -- Message text
                @ErrorSeverity, -- Severity
                @ErrorState     -- State
            );
    End
    Else
    Begin
        Select 'Found Something'
    End
END Try
Begin Catch

            SELECT 
                @ErrorMessage = ERROR_MESSAGE(),
                @ErrorSeverity = ERROR_SEVERITY(),
                @ErrorState = ERROR_STATE();

                RAISERROR (@ErrorMessage, -- Message text.
                   @ErrorSeverity, -- Severity.
                @ErrorState -- State.
                );
End Catch

【问题讨论】:

    标签: c# sql-server


    【解决方案1】:

    ExecuteNonQuery 返回受DELETEINSERTUPDATE 语句影响的行数 - 因为这就是它的典型用途。它确实NOT返回从SELECT 语句中选择的行数——而是返回-1。

    但是:由于 ExecuteNonQuery 调用不会让您有机会实际获取返回的数据,因此使用 SELECT 确实没有多大意义 - 您应该使用而是调用ExecuteReader,它返回一个SqlDataReader,然后您可以使用它来迭代SELECT 语句返回的数据,并以您需要的任何方式使用该数据。

    【讨论】:

    • 我真的不需要返回的数据,如果Select语句找到任何符合条件的记录,则认为测试成功。我可以看到这是一种特殊情况,与 ExecuteNonQuery 的目的不符。我将对我的 C# 代码进行一些更改,以便我可以根据实际需求选择查询执行的类型。我试图保持这个通用性,以便我的 C# 程序可用于在数据库上执行任何测试或执行任何命令。谁知道也许有一天我会发布它:) 一旦我开始工作,我会将此标记为已回答。谢谢
    【解决方案2】:

    对于 UPDATE、INSERT 和 DELETE 语句,返回值是受命令影响的行数。当正在插入或更新的表上存在触发器时,返回值包括受插入或更新操作影响的行数以及受一个或多个触发器影响的行数。

    对于所有其他类型的语句,返回值为 -1。如果发生回滚,返回值也是-1。

    如果我们通过 ExecuteNonQuery 运行存储过程,它将始终返回 -1

    另见this page

    【讨论】:

    • 我不确定我是否同意“通过 ExecuteNonQuery 运行的存储过程将始终返回 -1”的说法,我正在这样做,至少对于插入语句它有效。看起来我必须编辑我的程序并包含一个当我的 SQL 是选择语句时调用 ExecuteReader 的开关。
    • 本页最后一段可以帮到你docs.microsoft.com/en-us/dotnet/api/…
    猜你喜欢
    • 1970-01-01
    • 2016-02-28
    • 1970-01-01
    • 2011-12-28
    • 2011-12-09
    • 1970-01-01
    • 2012-03-18
    相关资源
    最近更新 更多