Mam tabelę Wiadomości z identyfikatorem kolumn (klucz podstawowy, autoincrement) i Treść (tekst).
Mam tabelę Użytkownicy z kolumnami nazwa użytkownika (klucz podstawowy, tekst) i hash.
Wiadomość jest wysyłana przez jednego Nadawcę (użytkownika) do wielu odbiorców (użytkownika), a odbiorca (użytkownik) może mieć wiele wiadomości.
Utworzyłem tabelę Messages_Recipients z dwiema kolumnami: MessageID (odnosząca się do kolumny ID w tabeli Messages i Recipient (odnosząca się do kolumny nazwa użytkownika w tabeli Users).
Więc mam takie pytanie. Identyfikator nowej wiadomości zostanie utworzony po jej zapisaniu w bazie danych. Ale jak mogę przechowywać odniesienie do MessageRow, który właśnie dodałem, aby pobrać ten nowy MessageID?
Zawsze mogę oczywiście przeszukać bazę danych pod kątem ostatniego dodanego wiersza, ale to może zwrócić inny wiersz w środowisku wielowątkowym?
EDYCJA: Jak rozumiem dla SQLite, możesz użyć SELECT last_insert_rowid()
. Ale jak nazwać to oświadczenie z ADO.Net?
Mój kod trwałości (wiadomości i wiadomościRecipients to 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);
}
źródło
Odpowiedzi:
W przypadku SQL Server należy SELECT SCOPE_IDENTITY (), aby uzyskać ostatnią wartość tożsamości dla bieżącego procesu.
W przypadku SQlite wygląda na to, że zrobisz to automatycznie
SELECT last_insert_rowid()
natychmiast po włożeniu wkładu.
http://www.mail-archive.com/[email protected]/msg09429.html
W odpowiedzi na Twój komentarz, aby uzyskać tę wartość, chciałbyś użyć kodu SQL lub OleDb, takiego jak:
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(); }
źródło
If the table has a column of type INTEGER PRIMARY KEY then that column is another alias for the rowid.
Inną opcją jest przyjrzenie się tabeli systemowej
sqlite_sequence
. Twoja baza danych sqlite będzie miała tę tabelę automatycznie, jeśli utworzyłeś tabelę z kluczem podstawowym autoincrement. Ta tabela jest przeznaczona dla sqlite do śledzenia pola autoincrement, aby nie powtarzał klucza podstawowego nawet po usunięciu niektórych wierszy lub po niepowodzeniu wstawiania (więcej informacji na ten temat można znaleźć tutaj http://www.sqlite.org/autoinc .html ).Tak więc z tą tabelą jest dodatkowa korzyść, że możesz znaleźć klucz podstawowy nowo wstawionego elementu nawet po wstawieniu czegoś innego (oczywiście w innych tabelach!). Po upewnieniu się, że Twoja wstawka się powiodła (w przeciwnym razie otrzymasz fałszywą liczbę), wystarczy zrobić:
select seq from sqlite_sequence where name="table_name"
źródło
Miałem problemy z używaniem
SELECT last_insert_rowid()
w środowisku wielowątkowym. Jeśli inny wątek wstawi do innej tabeli, która ma autoinc, last_insert_rowid zwróci wartość autoinc z nowej tabeli.Oto, gdzie stwierdzają to w dokumencie:
To pochodzi z sqlite.org doco
źródło
Przykładowy kod z rozwiązania @polyglot
SQLiteCommand sql_cmd; sql_cmd.CommandText = "select seq from sqlite_sequence where name='myTable'; "; int newId = Convert.ToInt32( sql_cmd.ExecuteScalar( ) );
źródło
Zgodnie z Android Sqlite pobierz ostatni identyfikator wiersza wstawiania, istnieje inne zapytanie:
SELECT rowid from your_table_name order by ROWID DESC limit 1
źródło
ORDER BY
. Powinno być szybciej, ale nie testowałem tego:SELECT MAX(rowid) FROM your_table_name