SCOPE_IDENTITY не работает в asp.net? - PullRequest
5 голосов
/ 28 января 2010

Я пытаюсь вставить запись и получить ее недавно сгенерированный идентификатор, выполняя два запроса один за другим, но не знаю, почему она выдает мне следующую ошибку.

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

А также, если возможно, проверьте, хорошо ли закодирован вышеуказанный код, или мы можем оптимизировать его для повышения производительности?

Спасибо

Ответы [ 2 ]

10 голосов
/ 28 января 2010

Вызов 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 и блока кода после комментария "// получение последнего вставленного идентификатора видео".

0 голосов
/ 28 января 2010

SCOPE_IDENTITY() должен быть извлечен из первой команды (SELECT, RETURN или OUT) и передан следующей команде. Под этим я подразумеваю, что SELECT_IDENTITY() должен находиться в конце команды first . В SQL 2008 существует дополнительный синтаксис для возврата значений как части INSERT, что делает это проще.

Или более эффективно: объедините команды в одну, чтобы избежать обходов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...