Я пытаюсь вставить запись и получить ее недавно сгенерированный идентификатор путем выполнения двух запросов один за другим, но не знаю почему ее предоставление мне следующая ошибка.
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();
}
}
}
И также, если это возможно, проверьте, вышеупомянутый код, кодированный хорошо, или мы можем оптимизировать его больше для, улучшают производительность?
Спасибо
Вызов 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 и блока кода, следующего за комментарием «// получение последнего вставленного идентификатора видео».
SCOPE_IDENTITY ()
следует извлечь из первой команды ( SELECT
, RETURN
или OUT
) и перешли в следующую команду. Под этим я подразумеваю, что SELECT_IDENTITY ()
должен быть в конце первой команды. В SQL 2008 есть дополнительный синтаксис для возврата значений как часть INSERT
, что упрощает эту задачу.
Или, что более эффективно: объедините команды в одну, чтобы избежать повторных обращений.