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


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

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

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

мой код сохраняемости (сообщения и messagesRecipients-это Таблицы данных):

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 56

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 получить последний идентификатор строки вставки есть еще один запрос:

SELECT rowid from your_table_name order by ROWID DESC limit 1