@@ IDENTITY после оператора INSERT всегда возвращает 0 - PullRequest
13 голосов
/ 09 октября 2008

Мне нужна функция, которая выполняет оператор INSERT для базы данных и возвращает первичный ключ Auto_Increment. У меня есть следующий код C #, но, хотя оператор INSERT работает нормально (я вижу запись в базе данных, PK генерируется правильно и строки == 1), значение id всегда равно 0. Любые идеи о том, что может происходить неправильно?

    public int ExecuteInsertStatement(string statement)
    {
        InitializeAndOpenConnection();
        int id = -1;


        IDbCommand cmdInsert = connection.CreateCommand();
        cmdInsert.CommandText = statement;
        int rows = cmdInsert.ExecuteNonQuery();

        if (rows == 1)
        {
            IDbCommand cmdId = connection.CreateCommand();
            cmdId.CommandText = "SELECT @@Identity;";
            id = (int)cmdId.ExecuteScalar();
        }

        return id;
    }
    private void InitializeAndOpenConnection()
    {
        if (connection == null)
            connection = OleDbProviderFactory.Instance.CreateConnection(connectString);

        if(connection.State != ConnectionState.Open)                 
            connection.Open();
    }

В ответ на ответы я попробовал:

public int ExecuteInsertStatement(string statement, string tableName)
    {
        InitializeAndOpenConnection();
        int id = -1;
        IDbCommand cmdInsert = connection.CreateCommand();
        cmdInsert.CommandText = statement + ";SELECT OID FROM " + tableName + " WHERE OID = SCOPE_IDENTITY();";
        id = (int)cmdInsert.ExecuteScalar();

        return id;
    }

но теперь я получаю сообщение об ошибке «Обнаружены символы после завершения оператора SQL»

Я использую базу данных MS Access с подключением OleDb, Provider = Microsoft.Jet.OLEDB.4.0

Ответы [ 13 ]

0 голосов
/ 09 октября 2008

Когда вы используете Access, посмотрите на эту статью от aspfaq, прокрутите вниз примерно до половины пути вниз по странице. Код написан на классическом ASP, но, надеюсь, принципы должны оставаться в силе.


Я считаю, что SELECT @@ Identity считается отдельным контекстом выполнения. Код, который должен работать, будет:

public int ExecuteInsertStatement(string statement)
{
    InitializeAndOpenConnection();

    IDbCommand cmdInsert = connection.CreateCommand();
    cmdInsert.CommandText = statement + "; SELECT @@Identity";
    object result = cmdInsert.ExecuteScalar();

    if (object == DBNull.Value)
    {
       return -1;
    }
    else
    {
       return Convert.ToInt32(result);
    }
}

Возможно, вы захотите / должны привести в порядок конкатенацию, которая добавляет «SELECT @@ Identity» в конец кода.

0 голосов
/ 09 октября 2008

Я думаю, что @@ идентичность действительна только в области действия команды - в вашем случае, когда вы выполняете «оператор».

Измените свой «оператор», чтобы сама хранимая процедура возвращала значение @@ IDENTITY сразу после оператора INSERT, и считывала его как код возврата выполнения хранимой процедуры.

0 голосов
/ 09 октября 2008

Есть ли на вашей таблице триггеры, которые могут быть вставлены в другие таблицы? Как правило, мы не рекомендуем использовать @@ Identity в пользу IDENT_CURRENT , чтобы вы могли гарантировать, что возвращенная идентификация относится к только что вставленной таблице.

...