J'ai une table Messages avec les colonnes ID (clé primaire, auto-incrémentation) et contenu (texte).
J'ai un tableau Utilisateurs avec colonnes nom d'utilisateur (clé primaire, texte) et Hash.
Un message est envoyé par un expéditeur (utilisateur) à plusieurs destinataires (utilisateur) et un destinataire (utilisateur) peut avoir plusieurs messages.
J'ai créé une table Messages_Recipients avec deux colonnes: MessageID (en référence à la colonne ID du tableau Messages et le destinataire (en référence à la colonne Nom d'utilisateur dans le tableau Utilisateurs). Ce tableau représente la relation plusieurs à plusieurs entre les destinataires et les destinataires. messages.
Donc, la question que j'ai est la suivante. L'identifiant d'un nouveau message sera créé après son stockage dans la base de données. Mais comment puis-je conserver une référence au MessageRow que je viens d’ajouter afin de récupérer ce nouveau MessageID?
Je peux toujours rechercher dans la base de données la dernière ligne ajoutée, bien sûr, mais cela pourrait éventuellement renvoyer une ligne différente dans un environnement multithread?
EDIT: Si je comprends bien pour SQLite, vous pouvez utiliser le SELECT last_insert_rowid()
. Mais comment puis-je appeler cette déclaration de ADO.Net?
Mon code de persistance (messages et messagesRecipients sont des 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);
}
Avec SQL Server, vous sélectionniez SCOPE_IDENTITY () pour obtenir la dernière valeur d’identité du processus en cours.
Avec SQlite, cela ressemble à un auto-incrément que vous feriez
SELECT last_insert_rowid()
immédiatement après votre insertion.
http://www.mail-archive.com/[email protected]/msg09429.html
En réponse à votre commentaire pour obtenir cette valeur, vous voudriez utiliser du code SQL ou OleDb comme:
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();
}
Une autre option consiste à consulter la table système sqlite_sequence
. Votre table sqlite aura automatiquement cette table si vous avez créé une table avec une clé primaire auto-incrémentée. Cette table est destinée à sqlite pour garder une trace du champ auto-incrémentation afin qu’il ne répète pas la clé primaire, même après la suppression de certaines lignes ou après l’échec d’une insertion (en savoir plus à ce sujet ici http: //www.sqlite .org/autoinc.html ).
Donc, avec cette table, il y a l'avantage supplémentaire que vous pouvez trouver la clé primaire de votre nouvel élément inséré même après avoir inséré autre chose (dans d'autres tables, bien sûr!). Après vous être assuré que votre insertion est réussie (sinon, vous obtiendrez un faux numéro), il vous suffira de faire:
select seq from sqlite_sequence where name="table_name"
J'ai eu des problèmes avec l'utilisation de SELECT last_insert_rowid()
dans un environnement multithread. Si un autre thread est inséré dans une autre table avec un autoinc, last_insert_rowid renverra la valeur autoinc de la nouvelle table.
Voici où ils déclarent cela dans le doco:
Si un thread séparé effectue un nouvel INSERT sur la même connexion à la base de données alors que la fonction sqlite3_last_insert_rowid () est en cours d'exécution et modifie ainsi le dernier insert rowid, la valeur renvoyée par sqlite3_last_insert_rowid () est imprévisible et peut ne pas correspondre à l'ancien ou au dernier. insérez rowid.
C'est à partir de sqlite.org doco
Exemple de code de la solution @polyglot
SQLiteCommand sql_cmd;
sql_cmd.CommandText = "select seq from sqlite_sequence where name='myTable'; ";
int newId = Convert.ToInt32( sql_cmd.ExecuteScalar( ) );
Selon Android Sqlite obtient la dernière ligne insérée il y a une autre requête:
SELECT rowid from your_table_name order by ROWID DESC limit 1