【问题标题】:How to get to get the value of @@identity or SELECT SCOPE_IDENTITY() from stored procedure in C# code?如何从 C# 代码中的存储过程中获取 @@identity 或 SELECT SCOPE_IDENTITY() 的值?
【发布时间】:2019-05-24 20:58:19
【问题描述】:

我使用的是 SQL Server 2012。在这个存储过程中,我想获取 @@identitySELECT SCOPE_IDENTITY() 的值。 intMyIdentity 是标识列。

CREATE PROCEDURE [spMyInsert] 
    (@vchVar AS VARCHAR(20), 
     @fltVar AS FLOAT)
AS
    SELECT TOP 1 intMyIdentity 
    FROM MyTbl  
    WHERE vchVar = @vchVar

    IF @@rowcount = 0
    BEGIN
        INSERT INTO MyTbl (vchVar, fltVar) 
        VALUES (@vchVar, @fltVar)

        SELECT @@identity AS intMyIdentity 
        -- SELECT SCOPE_IDENTITY()
    END

如何在 C# 中获取 @@identitySELECT SCOPE_IDENTITY() 的值?

当使用ExecuteScalar时,它返回0,而不是正确的值。

SqlConnection oConn = new SqlConnection(ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString);
oConn.Open();

mCommand.CommandText = "spMyInsert";
mCommand.Parameters.Add(new SqlParameter("@vchVar", txtMyVar.Text));
mCommand.Parameters.Add(new SqlParameter("@fltVar", dblMyVar));
mCommand.Connection = oConn;
mCommand.CommandType = CommandType.StoredProcedure; 

intMyIdentity = Convert.ToInt32(mCommand.ExecuteScalar());  --> this always return 0
oConn.Close();

已编辑:此查询有效

IF NOT EXISTS (SELECT 1 FROM myTbl WHERE vchVar = @vchVar)
BEGIN
    INSERT INTO myTbl (vchVar, fltVar)
    VALUES (@vchVar, @fltVar)

    SELECT SCOPE_IDENTITY()
END

【问题讨论】:

  • mCommand.ExecuteReader(): using (var reader = mCommand.ExecuteReader()) { while (reader.Read()) { ... } }。 Stack Overflow 上会有很多例子。
  • 您将始终得到以这种方式执行的第一个SELECT 语句的结果,因为它会生成一个结果集。将支票折叠到带有INSERT ... WHERE NOT EXISTS (SELECT 1 FROM MyTbl WHERE vchVar = @vchVar) 的语句中;这也修复了并发插入的漏洞。

标签: c# sql-server sql-server-2012 identity sqlcommand


【解决方案1】:

当您使用 ExecuteScalar 时,您的存储过程必须返回 @@identity。类似 RETURN @@IDENTITY;

【讨论】:

  • 首先,ExecuteScalar 不访问返回值,而是访问第一行的第一列。获取返回值意味着为它分配一个参数,这实际上更加复杂。其次,存储过程的返回值只能是单个 INT —— 在您拥有一个具有 BIGINT 标识的表之前,它可以正常工作,因此不是一个面向未来的解决方案。
  • ExecuteReader 在 reader.Read 中不返回任何内容:SqlDataReader reader = mCommand.ExecuteReader(); while (reader.Read()) //--> 它不会进入这个 while 循环 { .. }
  • 我把存储过程改成RETURN @@IDENTITY或者RETURN SCOPE_IDENTITY(),intMyIdentity还是返回0
  • 基于 Jeroen Mostert 的想法,我更新了查询以使用“IF NOT EXISTS”,这很有效。我已经用修复更新了原始帖子。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-01
  • 2018-10-15
  • 2017-02-14
  • 1970-01-01
相关资源
最近更新 更多