我试图通过逐个执行两个查询来插入记录并获取其新生成的id,但不知道为什么它会给我以下错误。
Object cannot be cast from DBNull to other types
我的代码如下:(我不想使用sql存储过程)
SqlParameter sqlParam;
int lastInsertedVideoId = 0;
using (SqlConnection Conn = new SqlConnection(ObjUtils._ConnString))
{
Conn.Open();
using (SqlCommand sqlCmd = Conn.CreateCommand())
{
string sqlInsertValues = "@Name,@Slug";
string sqlColumnNames = "[Name],[Slug]";
string sqlQuery = "INSERT INTO videos(" + sqlColumnNames + ") VALUES(" + sqlInsertValues + ");";
sqlCmd.CommandText = sqlQuery;
sqlCmd.CommandType = CommandType.Text;
sqlParam = sqlCmd.Parameters.Add("@Name", SqlDbType.VarChar);
sqlParam.Value = txtName.Text.Trim();
sqlParam = sqlCmd.Parameters.Add("@Slug", SqlDbType.VarChar);
sqlParam.Value = txtSlug.Text.Trim();
sqlCmd.ExecuteNonQuery();
//getting last inserted video id
sqlCmd.CommandText = "SELECT SCOPE_IDENTITY() AS [lastInsertedVideoId]";
using (SqlDataReader sqlDr = sqlCmd.ExecuteReader())
{
sqlDr.Read();
lastInsertedVideoId = Convert.ToInt32(sqlDr["lastInsertedVideoId"]);
}
}
}
//tags insertion into tag table
if (txtTags.Text.Trim().Length > 0 && lastInsertedVideoId > 0)
{
string sqlBulkTagInsert = "";
string[] tags = txtTags.Text.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
foreach (string tag in tags)
{
sqlBulkTagInsert += "INSERT INTO tags(VideoId, Tag) VALUES(" + lastInsertedVideoId + ", " + tag.Trim().ToLowerInvariant()+ "); ";
}
using (SqlConnection Conn = new SqlConnection(ObjUtils._ConnString))
{
Conn.Open();
using (SqlCommand sqlCmd = Conn.CreateCommand())
{
string sqlQuery = sqlBulkTagInsert;
sqlCmd.CommandText = sqlQuery;
sqlCmd.CommandType = CommandType.Text;
sqlCmd.ExecuteNonQuery();
}
}
}
如果可能的话,请检查以上代码是否编码好,或者我们可以对其进行更优化以提高性能?
由于
答案 0 :(得分:10)
对SCOPE_IDENTITY()的调用不会被视为与您正在执行的INSERT命令位于同一“范围”。
基本上,您需要做的是更改一行:
string sqlQuery = "INSERT INTO videos(" + sqlColumnNames + ") VALUES(" + sqlInsertValues + ");";
为:
string sqlQuery = "INSERT INTO videos(" + sqlColumnNames + ") VALUES(" + sqlInsertValues + "); SELECT SCOPE_IDENTITY() AS [lastInsertedVideoId]";
然后致电
int lastVideoInsertedId = Convert.ToInt32(sqlCmd.ExecuteScalar());
而不是.ExecuteNonQuery和“//获取最后插入的视频ID”注释后的代码块。
答案 1 :(得分:0)
应从第一个命令(SCOPE_IDENTITY()
,SELECT
或RETURN
中提取OUT
并传递给下一个命令。这样,我的意思是SELECT_IDENTITY()
应该在第一个命令的末尾。在SQL 2008中,还有一些额外的语法可以将值作为INSERT
的一部分返回,这使得这更简单。
或者更有效:将命令合并为一个以避免往返。