it-roy-ru.com

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

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

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

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

Мой код персистентности (сообщения и сообщения Получатели являются таблицами данных):

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);
}
66
Dabblernl

В SQL Server вы бы выбрали SELECT 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();
}
68
MikeW

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

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

select seq from sqlite_sequence where name="table_name"
98
polyglot

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

Вот где они утверждают, что в документе:

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

Это из sqlite.org doco

8
Fidel

Пример кода из решения @polyglot

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

Согласно Android Sqlite получает последний идентификатор строки вставки есть другой запрос:

SELECT rowid from your_table_name order by ROWID DESC limit 1
1
CoolMind