【问题标题】:T-SQL: returning the new INSERT identity to C#T-SQL:将新的 INSERT 标识返回给 C#
【发布时间】:2015-01-27 08:43:49
【问题描述】:

我正在使用存储过程将值放入 SQL Server。该过程将向添加的行添加一个 ID。我需要将此 ID 恢复到我的代码中。

目前我可以在 Visual Studio 的 OUTPUT 窗口中看到输出 id,但似乎无法在我的代码中捕获它。这是 proc 的摘要版本:

SQL

CREATE PROCEDURE dbo.DoSomething
(
    @var1 INT = NULL,
    @var2 INT = NULL,
    @var3 DATE = NULL
)
AS

BEGIN

    INSERT INTO atable
    (
        vara,
        varb,
        varc
    )
    VALUES
    (
        @var1,
        @var2,
        @var3
    )

    RETURN SCOPE_IDENTITY()

END

C#:

int result = 0;

/// create command
SqlCommand cmd = new SqlCommand("DoSomething", this.OpenSqlConnection());
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@var1", thing.value1);
cmd.Parameters.AddWithValue("@var2", thing.value2);
cmd.Parameters.AddWithValue("@var3", thing.value3);


/// send data to db
result = (int)cmd.ExecuteScalar();

所以我收到一个错误:对象引用未设置为对象的实例。当它到达 (int)cmd.ExecuteScalar() 时。

有什么想法吗?

【问题讨论】:

  • 与您遇到的错误没有直接关系,但不要将 RETURN 与 SCOPE_IDENTITY() 一起使用。存储过程只允许 RETURN 使用数据类型 int。由于您的身份可以采用其他数据类型,因此您可能会返回非 int 数据类型的内容。

标签: c# sql return-value scope-identity


【解决方案1】:
...
SELECT SCOPE_IDENTITY()

RETURN 值实际上是作为一个特殊的 OUTPUT 参数返回的。 SELECT 为 ExecuteScalar 提供了一个结果集。

您也可以使用 OUTPUT 子句代替单独的 SELECT:

...
AS
BEGIN
    INSERT INTO atable
    (
        vara,
        varb,
        varc
    )
    OUTPUT INSERTED.IDCol
    VALUES
    (
        @var1,
        @var2,
        @var3
    )
END
GO

这也适用于多行。

【讨论】:

  • 只是为了向其他人澄清您的声明,“OUPUT INSERTED.IDCol”行,IDCol 指的是您指定为身份的 ID 列。因此,如果您的列名是“TableId”,那么它将是 OUTPUT INSERTED.TableId
【解决方案2】:

您需要添加另一个参数,其方向为ReturnValue

var param = cmd.Parameters.Create("@ReturnValue");
param.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add(param);

这个参数执行后的值就是返回值:

var newId = cmd.Parameters["@ReturnValue"].Value;

Or

var newId = param.Value;

【讨论】:

  • 嗨,我无法正确返回。 (还是)感谢你的建议。在尝试了多种方法后,我最终尝试了@gbn 的建议,这似乎奏效了。
  • @Tomaszewski - 请注意我的原始代码没有将参数添加到参数集合中。答案已更新。
  • 对,它是一个单独的参数变量。我在存储过程中添加了 @ReturnValue 参数。我不断得到一个值,它总是数字 8。我不知道为什么。
  • @Tomaszewski - 您不需要将 ReturnValue 参数添加到存储过程参数列表中,您可以使用 RETURN 语句。
【解决方案3】:
SqlParameter retval = cmd.Parameters.Add("@returnValue", SqlDbType.Int); 
            retval.Direction = ParameterDirection.ReturnValue;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-31
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多