[英]2 rows inserted instead of 1 when using @@IDENTITY / scope_identity()
[英]Retrieving the last inserted ID using scope_Identity()
我正在嘗試使用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.Data.dll中發生類型'System.IndexOutOfRangeException'的異常,但未在用戶代碼中處理。
附加信息:此SqlParameterCollection不包含帶有ParameterName'@id_user'的SqlParameter。
我決定拆分兩個請求。 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();
}
}
}
您不應將查詢分為兩個查詢。 您應該在插入查詢中選擇/設置結果。
我為您提供了一個示例:
第一種方法是使用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;
}
}
最好的辦法是,如果查詢是靜態的,請將這些查詢放入存儲過程中。 這樣可以加快查詢速度。
如評論中所述:
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語句語法的更新。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.