Идентификатор возврата на INSERT?

У меня есть запрос INSERT, и я хочу, чтобы DB возвращал идентификатор только что вставленной строки.

sqlString = "INSERT INTO MagicBoxes (OwnerID, Key, Name, Permissions, Active, LastUpdated) VALUES (@OwnerID, @BoxKey, @BoxName, 0, 1, @Date) SET @ID = SCOPE_IDENTITY();";
cmd = new SqlCommand(sqlString, con);
cmd.Parameters.AddWithValue("@OwnerID", OwnerID);
cmd.Parameters.AddWithValue("@BoxKey", BoxKey);
cmd.Parameters.AddWithValue("@BoxName", BoxName);
cmd.Parameters.AddWithValue("@Username", Username);
cmd.Parameters.AddWithValue("@Date", DateTime.Now);
cmd.ExecuteNonQuery();

У меня в настоящее время это, я не уверен, что мне нужно сделать дальше...

Ответ 1

Вам просто нужно добавить @ID в коллекцию params, а затем восстановить его, как это,

cmd.Parameters.Add("@ID", SqlDbType.Int, 4).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
//Now just read the value of: cmd.Parameters["@ID"].value

Или, если вы предпочитаете этот синтаксис:

SqlParameter param = new SqlParameter("@ID", SqlDbType.Int, 4);
param.Direction = ParameterDirection.Output;
cmd.Parameters.Add(param);

Ответ 2

У вас есть два варианта; вы можете объявить параметр Output под названием @ID; или - вы можете изменить конец на SELECT SCOPE_IDENTITY() и просто использовать:

int id = (int)cmd.ExecuteScalar();

Я предпочитаю подход с формальным параметром, но ExecuteScalar работает хорошо.

Ответ 3

Так как SQL Server 2008 было предложение OUTPUT, добавленное к синтаксису TSQL. Это позволяет вам иметь данные, на которые влияет запрос DML, добавленный в табличный поток данных.

Хотя запрос SCOPE_IDENTITY() после запроса возвращает правильную информацию, он заставляет SQL Server выполнять 2 запроса, в которых предложение вывода ограничивает это одним запросом.

Зная это, выполняемый запрос может быть изменен следующим образом (Предполагая, что [Id] - это имя идентификатора):

INSERT INTO MagicBoxes (OwnerID, [Key], Name, [Permissions], Active, LastUpdated) 
OUTPUT INSERTED.Id
VALUES (@OwnerID, @BoxKey, @BoxName, 0, 1, @Date)

Другая проблема заключается не в использовании SqlCommand. Большинство объектов Sql... в ADO.net реализуют IDisposable и должны быть утилизированы должным образом.

Объединяя все вместе, я бы выполнил эту часть кода следующим образом:

        using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["db"].ConnectionString))
        using (var cmd = new SqlCommand(@"
                INSERT INTO MagicBoxes (OwnerID, [Key], Name, [Permissions], Active, LastUpdated) 
                OUTPUT INSERTED.Id
                VALUES (@OwnerID, @BoxKey, @BoxName, 0, 1, @Date) ", conn))
        {
            cmd.Parameters.AddRange(new[]
                {
                    new SqlParameter("@OwnerID", SqlDbType.Int).Value = OwnerID,
                    new SqlParameter("BoxKey", SqlDbType.VarChar).Value = BoxKey, 
                    new SqlParameter("@BoxName", SqlDbType.VarChar).Value = BoxName, 
                    new SqlParameter("@Date", SqlDbType.DateTime).Value = DateTime.Now 
                });

            conn.Open();

            var id = (int)cmd.ExecuteScalar();
        }

Ответ 4

Добавьте это к вашим параметрам

SqlParameter IDParameter = new SqlParameter("@ID",SqlDbType.Int);
IDParameter.Direction = ParameterDirection.Output;
cmd.Parameters.Add(IDParameter);

После выполнения вы можете получить идентификатор

int id = (int)IDParameter.Value;

Ответ 5

Почему бы вам не вызвать процедуру хранилища. Передайте значения в процедуру хранилища, чтобы получить введенные значения, и из SP верните последнее начальное значение, вставленное с помощью SCOPE_IDENTITY(). Надейтесь на эту помощь.