【问题标题】:Stored procedure returns different values in C# vs. SQL Server存储过程在 C# 与 SQL Server 中返回不同的值
【发布时间】:2014-01-08 15:44:36
【问题描述】:

我有一个带有参数@id int OUTPUT 的存储过程(sql server 2012) 该过程向数据库的表中插入一些数据并返回受影响行的 ID

SET @id=SCOPE_IDENTITY()
RETURN @id

我从 SQL Server 测试它,它工作正常。但是当我从 C# 调用它时:它确实将数据插入到表中,但返回 null:

SqlParameter parm = new SqlParameter("@id", SqlDbType.Int);
parm.Size = 32;
parm.Direction = ParameterDirection.Output; // This is important!
cmd.Parameters.Add(parm);
object id = (int?)cmd.ExecuteScalar();//<-null

请指出导致这种奇怪行为的原因?

【问题讨论】:

  • @Steve - 抱歉 - 打错了
  • 请看我的 cmets 关于 Steve 和 Damith 的回答。简而言之,请不要使用 RETURN 来获取 IDENTITY 值,因为 RETURN 的数据类型仅为 INT 而 IDENTITY 可以是 BIGINT 等。

标签: c# sql sql-server stored-procedures sql-server-2012


【解决方案1】:

ID 的值存储在执行查询后可以读取的输出参数中。

SqlParameter parm = new SqlParameter("@id", SqlDbType.Int);
parm.Size = 32;
parm.Direction = ParameterDirection.Output; // This is important!
cmd.Parameters.Add(parm);
cmd.ExecuteNonQuery();
object id = (int)cmd.Parameters["@id"].Value;

或者您可以将查询本身更改为最后一行

SELECT SCOPE_IDENTITY()

并从 ExecuteScalar 中获取值(在这种情况下无需传递 ID 参数)

object result = cmd.ExecuteScalar();
if(result != null) 
    id = Convert.ToInt32(result);

【讨论】:

  • +1,因为使用 OUTPUT 参数是获取 SCOPE_IDENTITY() 的更好选择,它返回 NUMERIC(38,0) 并适用于 BIGINT、NUMERIC/DECIMAL 等 IDENTITY 字段。返回值仅为 INT。
【解决方案2】:
SqlParameter param = new SqlParameter("id", SqlDbType.Int);
param.Direction = ParameterDirection.ReturnValue;
cmdHeader.Parameters.Add(param);

    //   Execute your command
cmdHeader.ExecuteNonQuery();

    //   Get the return value
int returnvalue = (int)myCommand.Parameters["id"].Value;

【讨论】:

    【解决方案3】:

    你可以得到返回值

     parm.Direction = ParameterDirection.ReturnValue;
     cmd.Parameters.Add(parm);
     cmd.ExecuteNonQuery();
     var id = (int?)parm.Value;
    

    【讨论】:

    • 输出和返回值方向的区别是什么?
    • 因为你使用return @id,所以你必须使用ParameterDirection.ReturnValue,但你可以使用select @id作为ParameterDirection.Output
    • 你所说的引发了一个异常参数@id is not provided
    • @Yakov 需要将 parm 添加到 cmd
    • 虽然这确实显示了获取返回值的正确语法(这很好,并且从技术上回答了所提出的问题),但使用返回值来获取 IDENTITY 值是一种不好的做法。 IDENTITY 字段可以是 INT、BIGINT、NUMERIC/DECIMAL 等,但返回值只能是 INT。请使用 OUTPUT 参数,甚至通过 ExecuteScalar 使用 SELECT。
    【解决方案4】:

    关键部分在docs

    执行查询,并返回第一行的第一列 查询返回的结果集

    即ExecuteScalar 不返回返回值。如果您想以这种方式获取值,请在查询中选择值:

    SET @id=SCOPE_IDENTITY()
    SELECT @id
    

    或者简单地说:

    SELECT SCOPE_IDENTITY()
    

    当然,如果你的查询已经返回了一个结果集,那就没有什么好处了。

    如果你真的想要返回值,你需要使用ParameterDirection.ReturnValue而不是ParameterDirection.Output然后将其作为参数值读取:

    parm.Direction = ParameterDirection.ReturnValue;
    cmd.Parameters.Add(parm);
    int id = (int)cmd.Parameters["@id"].Value;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-23
      • 1970-01-01
      • 1970-01-01
      • 2016-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-31
      相关资源
      最近更新 更多