ADO.NET SqlCommand没有返回SCOPE_IDENTITY()的正确值

问题描述 投票:0回答:1

我有一张简单的桌子:

CREATE TABLE [MyTable]
(
    [ID] [INT] IDENTITY(1,1) NOT NULL,
    [NAME] [NVARCHAR](100) NOT NULL,
    [DATA] [NVARCHAR](max) NOT NULL,

    CONSTRAINT [PK_MyTable] 
        PRIMARY KEY CLUSTERED ([ID] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

我有一个存储过程,该存储过程在此表中插入一行并通过PK IDENTITY返回SCOPE_IDENTITY()列的值

CREATE PROCEDURE [InsertMyTable] 
    @NAME NVARCHAR(100),
    @DATA NVARCHAR(MAX)  
AS
BEGIN
    INSERT INTO [MyTable] ([NAME], [DATA])
    VALUES (@NAME, @DATA)  

    RETURN SCOPE_IDENTITY()
END

我已经通过SSMS和其他工具测试了此存储过程,并且其行为符合预期。

每次运行以下脚本时,返回值将增加1:

DELETE FROM [MyTable]
GO

DECLARE @return INT

EXEC @return = [InsertMyTable] @NAME='MyName', @DATA='Data'

SELECT @return
GO
  • 首次运行返回1
  • 第二次运行返回2

但是,当我使用System.Data.SqlClient在C#代码中执行类似操作时,存储过程的返回值始终为1。似乎并不能反映出每次删除并重新插入该行后,标识都会增加。

    using (var connection = new SqlConnection({connection-string}))
    using (var command = connection.CreateCommand())
    {
        command.CommandType = CommandType.Text;
        command.CommandText = "delete from [MyTable] where [NAME]='MyName'";

        connection.Open();

        command.ExecuteNonQuery();
    }

    using (var connection = new SqlConnection({connection-string}))
    using (var command = connection.CreateCommand())
    {
        command.CommandType = CommandType.StoredProcedure;
        command.CommandText = "InsertMyTable";

        command.Parameters.Add(new SqlParameter($"@NAME", "MyName"));
        command.Parameters.Add(new SqlParameter($"@DATA", "data"));

        connection.Open();

        var returnValue = command.ExecuteNonQuery();
    }
  • 首次运行returnValue = 1
  • 第二轮returnValue = 1
sql-server ado.net sqlcommand scope-identity
1个回答
1
投票

您的存储过程返回ID作为存储过程返回值,该ID仅应用于成功或失败,而不能用于数据。

[SqlCommand.ExecuteNonQuery()返回已执行批处理的所有行计数消息的总数。

您应该使用输出参数

CREATE PROCEDURE [InsertMyTable] 
  @NAME NVARCHAR(100)
, @DATA NVARCHAR(MAX) 
, @ID INT OUTPUT
AS
BEGIN
INSERT INTO [MyTable]
           ([NAME]
           ,[DATA])
     VALUES
           ( @NAME
           , @DATA)  
set @ID = SCOPE_IDENTITY()
END

或使用结果集,并使用SqlCommand.ExecuteScalar()或SqlCommand.ExecuteReader()获得值。

CREATE PROCEDURE [InsertMyTable] 
  @NAME NVARCHAR(100)
, @DATA NVARCHAR(MAX)  
AS
BEGIN
INSERT INTO [MyTable]
           ([NAME]
           ,[DATA])
     VALUES
           ( @NAME
           , @DATA)  
SELECT SCOPE_IDENTITY() ID
END

您可以通过绑定一个额外的SqlParameter来完成您的工作,但这是一个坏习惯。

© www.soinside.com 2019 - 2024. All rights reserved.