Как получить последний идентификатор autoincremented из таблицы SQLite?

у меня есть табличные сообщения с идентификатором столбцов (первичный ключ, автоинкремент) и контентом (текст).
У меня есть таблица пользователей со столбцами username (первичный ключ, текст) и Hash.
Сообщение отправляется одним отправителем (пользователем) многим получателям (пользователю), а получатель (пользователь) может иметь много сообщений.
Я создал таблицу Messages_Recipients с двумя столбцами: MessageID (ссылаясь на столбец ID таблицы Messages и Recipient (ссылаясь на столбец username в таблице Users). Эта таблица представляет отношение "многие ко многим" между получателями и сообщениями.

Итак, у меня есть вопрос. Идентификатор нового сообщения будет создан после его сохранения в базе данных. Но как я могу держать ссылку на MessageRow, который я только что добавил, чтобы получить этот Новый MessageID?
Я всегда могу искать в базе данных последнюю строку, добавленную, конечно, но это может вернуть другую строку в многопоточной среде?

EDIT: как я поймите это для SQLite вы можете использовать SELECT last_insert_rowid(). Но как я могу назвать это утверждение ADO.Net?

мой код персистентности (сообщения и messagesRecipients являются DataTables):

public void Persist(Message message)
{
    pm_databaseDataSet.MessagesRow messagerow;
    messagerow=messages.AddMessagesRow(message.Sender,
                            message.TimeSent.ToFileTime(),
                            message.Content,
                            message.TimeCreated.ToFileTime());
    UpdateMessages();
    var x = messagerow;//I hoped the messagerow would hold a
    //reference to the new row in the Messages table, but it does not.
    foreach (var recipient in message.Recipients)
    {
        var row = messagesRecipients.NewMessages_RecipientsRow();
        row.Recipient = recipient;
        //row.MessageID= How do I find this??
        messagesRecipients.AddMessages_RecipientsRow(row);
        UpdateMessagesRecipients();//method not shown
    } 

}

private void UpdateMessages()
{
    messagesAdapter.Update(messages);
    messagesAdapter.Fill(messages);
}

5 ответов


С SQL Server вы бы выбрали SCOPE_IDENTITY (), чтобы получить последнее значение идентификатора для текущего процесса.

С SQlite, похоже, для автоинкремента вы бы сделали

SELECT last_insert_rowid()

сразу после вставки.

http://www.mail-archive.com/sqlite-users@sqlite.org/msg09429.html

в ответ на ваш комментарий, чтобы получить это значение, вы хотели бы использовать код SQL или OleDb, например:

using (SqlConnection conn = new SqlConnection(connString))
{
    string sql = "SELECT last_insert_rowid()";
    SqlCommand cmd = new SqlCommand(sql, conn);
    conn.Open();
    int lastID = (Int32) cmd.ExecuteScalar();
}

еще один вариант-посмотреть системную таблицу sqlite_sequence. Ваша база данных sqlite будет иметь эту таблицу автоматически, если вы создали любую таблицу с первичным ключом autoincrement. Эта таблица предназначена для sqlite для отслеживания поля autoincrement, чтобы он не повторял первичный ключ даже после удаления некоторых строк или после неудачной вставки (подробнее об этом здесьhttp://www.sqlite.org/autoinc.html).

таким образом, с этой таблицей есть дополнительное преимущество, которое вы может узнать первичный ключ вашего вставленного элемента даже после того, как вы вставили что-то еще (в других таблицах, конечно!). Убедившись, что ваша вставка прошла успешно (в противном случае вы получите ложный номер), вам просто нужно сделать:

select seq from sqlite_sequence where name="table_name"

У меня были проблемы с использованием SELECT last_insert_rowid() в многопоточной среде. Если другой поток вставляет в другую таблицу, которая имеет autoinc, last_insert_rowid вернет значение autoinc из новой таблицы.

вот где они заявляют, что в укор:

Если отдельный поток выполняет новую вставку в том же соединении с базой данных во время выполнения функции sqlite3_last_insert_rowid() и, таким образом, изменяет последний идентификатор строки вставки, то значение, возвращаемое sqlite3_last_insert_rowid () непредсказуем и может не равняться ни старому, ни новому последнему идентификатору строки вставки.

все от sqlite.org укор


пример кода из @ polyglot solution

SQLiteCommand sql_cmd;
sql_cmd.CommandText = "select seq from sqlite_sequence where name='myTable'; ";
int newId = Convert.ToInt32( sql_cmd.ExecuteScalar( ) );

по данным Android Sqlite получить последнюю вставку строки id есть еще один запрос:

SELECT rowid from your_table_name order by ROWID DESC limit 1