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

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

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

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

Мой код Persistence (сообщения и сообщенияRecipients - это 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);
}

Ответ 1

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

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

SELECT last_insert_rowid()

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

http://www.mail-archive.com/[email protected]/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();
}

Ответ 2

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

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

select seq from sqlite_sequence where name="table_name"

Ответ 3

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

Здесь, где они утверждают, что в doco:

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

Что из sqlite.org doco

Ответ 4

Здесь пример кода из решения @polyglot

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