【问题标题】:Problem with getting last inserted ID from database - asp.net从数据库中获取最后插入的 ID 的问题 - asp.net
【发布时间】:2011-08-31 10:36:12
【问题描述】:

我正在尝试将数据添加到用户表(注册后)。将用户数据添加到用户表后,我不会立即在“配置文件”表 (1:1) 中创建带有用户 ID 的行,这就是我在这里使用事务的原因。但问题是当我收到的“ExecuteScalar()”行异常是"Object reference not set to an instance of an object."

    string sqlAddUser = string.Format("insert into tbl_users ([UserName],[Email],[Password],[PasswordSalt],[CreatedDate],[IsActivated],[IsLockedOut],[LastLoginDate],[LastLockedOutDate], [NewEmailKey]) values ('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}', '{9}')",
        user.UserName, user.Email, user.Password, user.PasswordSalt, user.CreatedDate, user.IsActivated, user.IsLockedOut, user.LastLockedOutDate, user.LastLoginDate, user.NewEmailKey);

    SqlCommand cmdAddUser = new SqlCommand(sqlAddUser, conn, transaction);
    int result = cmdAddUser.ExecuteNonQuery();

    SqlCommand cmdGetLastIdentity = new SqlCommand("SELECT @@IDENTITY", conn, transaction);                        
    int i = (int)cmdGetLastIdentity.ExecuteScalar();

    string sqlAddUserProfile = string.Format("insert into tbl_profile (UserId) values ({0})", i);
    SqlCommand cmdAddUserProfile = new SqlCommand(sqlAddUserProfile, conn, transaction);

    cmdAddUserProfile.ExecuteNonQuery();

    transaction.Commit();

    return GetUser(username);
}
catch (Exception ex)
{
    transaction.Rollback();
}

【问题讨论】:

  • 不要使用单独的查询来获取@@IDENTITY。在原始查询中返回 SCOPE_IDENTITY()。
  • 所以我可以从“sqlAddUser”查询中返回身份。你能提供一些示例代码吗?
  • 我刚刚注意到您正在使用串联构建查询。您应该立即停止此操作并使用参数化查询,否则您的网站极有可能通过 SQL 注入被黑客入侵。然后将;SELECT @newid = SCOPE_IDENTITY() 添加到参数化查询的末尾,并传入该名称的输出参数。抱歉不能提供示例代码,因此 cmets 不回答。希望其他人会!
  • 现在我只是构建查询以便稍后工作,我将添加参数。谢谢。

标签: c# asp.net sql-server database transactions


【解决方案1】:

您可以通过在 INSERT、UPDATE、DELETE 或 MERGE 语句中使用 OUTPUT 子句在单个语句中执行此操作。

cmd.CommandText = "INSERT INTO tbl_user (...) OUTPUT inserted.Id VALUES (...)";
var id = Convert.ToInt32(cmd.ExecuteScalar());

您可以输出任何数据库生成的值,并使用 SqlCommand.ExecuteReader() 读取这些值,它将执行插入并将插入的值作为表输出。

注意:不要使用字符串格式化,使用sql参数,否则容易被sql注入

【讨论】:

    【解决方案2】:

    其中一个 cmets 出现了 - 像这样构造您的插入,并且您要求进行 SQL 注入。以下是您可能应该做的事情:

    var cmdAddUser = new SqlCommand(@"insert into tbl_users (
                                          [UserName],
                                          [Email],
                                          [Password],
                                          [PasswordSalt],
                                          [CreatedDate],
                                          [IsActivated],
                                          [IsLockedOut],
                                          [LastLoginDate],
                                          [LastLockedOutDate], 
                                          [NewEmailKey]) 
                                      values (@p1, @p2, @p3, @p4, @p4, @p6, @p7, @p8, @p9, @p10); 
                                      select SCOPE_IDENTITY();", conn, transaction);
    
    cmdAddUser.Parameters.AddWithValue("@p1", user.UserName);
    cmdAddUser.Parameters.AddWithValue("@p2", user.Email);
    cmdAddUser.Parameters.AddWithValue("@p3", user.Password);
    cmdAddUser.Parameters.AddWithValue("@p4", user.PasswordSalt);
    cmdAddUser.Parameters.AddWithValue("@p5", user.CreateDate);
    cmdAddUser.Parameters.AddWithValue("@p6", user.IsActivated);
    cmdAddUser.Parameters.AddWithValue("@p7", user.IsLockedOut);
    cmdAddUser.Parameters.AddWithValue("@p8", user.LastLoginDate);
    cmdAddUser.Parameters.AddWithValue("@p9", user.LastLockedOutDate);
    cmdAddUser.Parameters.AddWithValue("@p10", user.NewEmailKey);
    
    var newId = (int)cmdAddUser.ExecuteNonQuery();
    
    // Then proceed with your profile operations using the result
    

    您可能已经这样做了,但我会将您的操作包装在 using 语句中,以便您正确处理数据库对象。

    【讨论】:

      【解决方案3】:

      你必须在服务器上创建一个存储过程来插入新用户并返回它的 id。

      【讨论】:

      • OP 根本不需要创建存储过程。参数化的即席 SQL 可以使用输出参数,也可以只使用 ExecuteScalar。存储过程问题完全无关紧要。
      猜你喜欢
      • 2019-09-14
      • 1970-01-01
      • 2010-12-07
      • 1970-01-01
      • 2015-03-20
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多