【问题标题】:Retrieving the last inserted ID using scope_Identity()使用 scope_Identity() 检索最后插入的 ID
【发布时间】:2014-01-27 18:08:26
【问题描述】:

我正在尝试使用 SCOPE_IDENTITY 获取最后插入的 ID,但出现错误。 我正在使用 SQL Server 2012 和 Visual Studio Express 2013

这是我的代码

protected void PerformInscription(string sEmail, string sPassword,string sName)
{
    bool buserIdAuthenticated = false;
    string salt = null;
    string passwordHash = pwdManager.GeneratePasswordHash(txtPassword.Text, out salt);

    SqlConnection sqlConnection;
    sqlConnection = new SqlConnection();

    try
    {
        sqlConnection.ConnectionString = sqlDataSource1.ConnectionString;

        string insertStatement = "INSERT INTO [User] "
                                 + "(email, hash, salt, name) "
                                 + "VALUES (@email, @hash, @salt, @name);"
                                 + "SELECT SCOPE_IDENTITY() AS id_user;";

        SqlCommand insertCommand = new SqlCommand(insertStatement, sqlConnection);

        insertCommand.Parameters.Add("@email", SqlDbType.VarChar, 50).Value = sEmail;
        insertCommand.Parameters.Add("@hash", SqlDbType.VarChar, 50).Value = passwordHash;
        insertCommand.Parameters.Add("@salt", SqlDbType.VarChar, 50).Value = salt;
        insertCommand.Parameters.Add("@nom", SqlDbType.VarChar, 50).Value = sName;

        sqlConnection.Open();

        int count = insertCommand.ExecuteNonQuery();

        int User_ID = Convert.ToInt32(insertCommand.Parameters["@id_user"].Value);
        Session["Id_user"] = User_ID;

        insertCommand.Dispose();

        if (count >= 1)
        {
            buserIdAuthenticated = true;                    
            Session["userIdAuthenticated"] = buserIdAuthenticated;
            Response.Redirect("../pages/Welcome.aspx");
        }
    }

    catch (SqlException ex)
    {
        lblMessage.Text = ex.Message;
    }

    finally
    {
        sqlConnection.Close();
    }
  }
}

我想捕获最后一个 user_id,它被定义为自动增量的身份。

这是我得到的错误

“System.IndexOutOfRangeException”类型的异常发生在 System.Data.dll,但未在用户代码中处理。

附加信息:带有 ParameterName '@id_user' 的 SqlParameter 不包含在此 SqlParameterCollection 中。

我决定拆分这两个请求。 1 个插入和 1 个选择

    SqlConnection sqlConnection;
    sqlConnection = new SqlConnection();

    try
    {
        sqlConnection.ConnectionString = sqlDataSource1.ConnectionString;

        string insertStatement = "INSERT INTO [User] "
                                 + "(email, hash, salt, name) "
                                 + "VALUES (@email, @hash, @salt, @name)";

        SqlCommand insertCommand = new SqlCommand(insertStatement, sqlConnection);

        insertCommand.Parameters.Add("@email", SqlDbType.VarChar, 50).Value = sEmail;
        insertCommand.Parameters.Add("@hash", SqlDbType.VarChar, 50).Value = passwordHash;
        insertCommand.Parameters.Add("@salt", SqlDbType.VarChar, 50).Value = salt;
        insertCommand.Parameters.Add("@name", SqlDbType.VarChar, 50).Value = sName;

        sqlConnection.Open();

        int count = insertCommand.ExecuteNonQuery();

        insertCommand.Dispose();

        if (count >= 1)
        {
            string selectStatement = "SELECT SCOPE_IDENTITY() AS id_user";
            SqlCommand selectCommand = new SqlCommand(selectStatement, sqlConnection);
            selectCommand.Parameters.Add("@Id_user", SqlDbType.Int, 0, "Id_user");
            int newID = (int)selectCommand.ExecuteScalar();

            int User_ID = Convert.ToInt32(selectCommand.Parameters["@Id_user"].Value);
            Session["Id_user"] = User_ID;

            buserIdAuthenticated = true;                   
            Session["userIdAuthenticated"] = buserIdAuthenticated;
            Response.Redirect("../pages/Bienvenue.aspx");
        }
    }

    catch (SqlException ex)
    {
        lblMessage.Text = ex.Message;
    }

    finally
    {
        sqlConnection.Close();
    }
  }
 }

【问题讨论】:

  • SCOPE_IDENTIY != SCOPE_IDENTITY
  • 我没有看到参数中定义的@id_user,你也应该将它声明为输出参数。在这里查看一些信息:msdn.microsoft.com/en-us/library/59x02y99(v=vs.110).aspx
  • This 可能会有所帮助。
  • 你能重新打开这个问题吗,因为我用新问题重写了标题,谢谢
  • @JoachimIsaksson 我正在尝试找到提取 scope_Identity() 的好答案;我添加了以下行“SELECT SCOPE_IDENTITY() AS id_user;”; insertCommand.Parameters.Add("@id_user", SqlDbType.Int,0,"Id_user");但我有这个错误参数化查询'(@email varchar(50),@hash varchar(50),@salt varchar(50),@name'需要参数'@id_user',它没有提供。任何想法?

标签: c# asp.net sql-server-2012


【解决方案1】:

您不应将查询拆分为两个查询。您应该在插入查询中选择/设置结果。

我为你做了一个例子:

第一种方法是使用select返回单个值

private void Method1()
{
    string sEmail = "test@test.com";
    string passwordHash = "#$@#$@!#@$$@#!#@$!#@$!";
    string salt = "????";
    string sName = "John";

    using (SqlConnection sqlConnection = new SqlConnection(_connectionString))
        try
        {
            sqlConnection.Open();

            string insertStatement = "INSERT INTO [User] "
                                        + "(email, hash, salt, name) "
                                        + "VALUES (@email, @hash, @salt, @name)"

                                        + "SELECT SCOPE_IDENTITY()";

            using (SqlCommand insertCommand = new SqlCommand(insertStatement, sqlConnection))
            {

                insertCommand.Parameters.Add("@email", SqlDbType.VarChar, 50).Value = sEmail;
                insertCommand.Parameters.Add("@hash", SqlDbType.VarChar, 50).Value = passwordHash;
                insertCommand.Parameters.Add("@salt", SqlDbType.VarChar, 50).Value = salt;
                insertCommand.Parameters.Add("@name", SqlDbType.VarChar, 50).Value = sName;


                int userId = Convert.ToInt32(insertCommand.ExecuteScalar());
                Trace.WriteLine("User created with id: " + userId);
            }
        }

        catch (SqlException ex)
        {
            Trace.WriteLine(ex.Message);
            //lblMessage.Text = ex.Message;
        }
}

第二种方法是定义一个输出参数,这样可以返回多个值。

private void Method2()
{
    string sEmail = "test@test.com";
    string passwordHash = "#$@#$@!#@$$@#!#@$!#@$!";
    string salt = "????";
    string sName = "John";

    using (SqlConnection sqlConnection = new SqlConnection(_connectionString))
        try
        {
            sqlConnection.Open();

            string insertStatement = "INSERT INTO [User] "
                                        + "(email, hash, salt, name) "
                                        + "VALUES (@email, @hash, @salt, @name)"

                                        + "SET @user_id = SCOPE_IDENTITY()";

            using (SqlCommand insertCommand = new SqlCommand(insertStatement, sqlConnection))
            {

                insertCommand.Parameters.Add("@email", SqlDbType.VarChar, 50).Value = sEmail;
                insertCommand.Parameters.Add("@hash", SqlDbType.VarChar, 50).Value = passwordHash;
                insertCommand.Parameters.Add("@salt", SqlDbType.VarChar, 50).Value = salt;
                insertCommand.Parameters.Add("@name", SqlDbType.VarChar, 50).Value = sName;

                insertCommand.Parameters.Add("@user_id", SqlDbType.Int).Direction = ParameterDirection.Output;

                insertCommand.ExecuteNonQuery();

                int userId = Convert.ToInt32(insertCommand.Parameters["@user_id"].Value);
                Trace.WriteLine("User created with id: " + userId);
            }
        }

        catch (SqlException ex)
        {
            Trace.WriteLine(ex.Message);
            //lblMessage.Text = ex.Message;
        }
}

如果查询是静态的,最好将这些查询放在存储过程中。这将加快查询速度。

【讨论】:

    【解决方案2】:

    如 cmets 中所述:

    string insertStatement = "INSERT INTO [User] "
                                     + "(email, hash, salt, name) "
                                     + "VALUES (@email, @hash, @salt, @name);"
                                     + "SELECT @id_user = SCOPE_IDENTIY();";
    

    应该是:

    string insertStatement = "INSERT INTO [User] "
                                     + "(email, hash, salt, name) "
                                     + "VALUES (@email, @hash, @salt, @name);"
                                     + "SELECT SCOPE_IDENTITY() AS id_user;";
    

    查看SCOPE_IDENTIY 和SCOPE_IDENTITY 之间的区别。

    并注意 SELECT 语句语法的更新。

    【讨论】:

    • 我进行了更改,现在出现错误必须声明标量变量“@id_user”。
    • @Jay 我正在尝试找到提取 scope_Identity() 的好答案;我添加了以下行“SELECT SCOPE_IDENTITY() AS id_user;”; insertCommand.Parameters.Add("@id_user", SqlDbType.Int,0,"Id_user");但我有这个错误参数化查询'(@email varchar(50),@hash varchar(50),@salt varchar(50),@name'需要参数'@id_user',它没有提供。任何想法?
    • 尝试使用 ExecuteScalar 函数?
    • 我现在收到这个错误,我找不到选择的问题参数化查询'(@Id_user int)SELECT SCOPE_IDENTITY()AS id_user'需要参数'@Id_user',它未提供。
    猜你喜欢
    • 1970-01-01
    • 2015-09-30
    • 1970-01-01
    • 2012-10-29
    • 2010-12-31
    • 2016-10-06
    • 2011-07-27
    • 1970-01-01
    相关资源
    最近更新 更多