2011-08-31 45 views
0

我想向用户表中添加数据(注册后)。在将用户数据添加到用户表后,我不想在'profile'表(1:1)中创建具有userID的行,这就是为什么我在这里使用事务。但问题是插入后,我无法获得用户ID的用户(@@标识)时,代码来“的ExecuteScalar()”行不同的是我收到的是"Object reference not set to an instance of an object."从数据库中获取最后插入的ID的问题 - asp.net

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(); 
} 
+0

不要使用单独的查询来获取'@@ IDENTITY'。在原始查询中返回'SCOPE_IDENTITY()'。 –

+0

所以我可以从'sqlAddUser'查询返回标识。你能提供一些实用的代码吗? – 1110

+1

我刚刚注意到你正在使用串联构建你的查询。您应该立即停止并使用参数化查询,否则您的网站极有可能通过SQL注入被黑客入侵。然后,您将在参数化查询的末尾添加'; SELECT @newid = SCOPE_IDENTITY()'并传入该名称的输出参数。对不起,不能提供示例代码,因此评论无法回答。希望别人会! –

回答

5

您可以通过在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注入

+0

+1'OUTPUT'条款同样适用。 –

-1

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

+0

OP不需要创建存储过程。参数化的adhoc SQL可以使用输出参数,也可以只使用ExecuteScalar。存储的proc问题完全不相关。 –

+0

@马丁史密斯:很高兴今天我学到了一些新东西 –

3

其中一个评论是在现场 - 构建你插入这样和你问的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声明你的操作,以便您妥善处置你的数据库对象。

相关问题