Die Identitäts-Spalte des zuletzt hinzugefügten Datensatzes auslesen

database
net
concurrency
multithreading
adonet
sql
Tags: #<Tag:0x00007f9add15d810> #<Tag:0x00007f9add15d6d0> #<Tag:0x00007f9add15d590> #<Tag:0x00007f9add15d450> #<Tag:0x00007f9add15d310> #<Tag:0x00007f9add15d1d0>

#1

Wenn Ihr mit ADO.NET einen neuen Datensatz einfügt, der über eine Identitäts-Spalte verfügt (also der z.B. automatisch seine eigene ID generiert und hochzählt), dann wollt Ihr ab und zu auch die ID dieses neu hinzugefügten Datensatzes direkt nach dem Einfügen haben.

Der Artikel “Getting the identity of the most recently added record” beschreibt das für verschiedene Datenbanken wie SQL Server und Microsoft Access (MDB) sehr anschaulich.

Sonderfall MS Access

Für MS Access geht das über SELECT @@IDENTITY.

In meinen eigenen Projekten hatte ich bei Microsoft-Access-Projekten manchmal das Phänomen, dass die falsche ID zurückgeliefert wurde, scheinbar eine zufällige ID.

Die Ursache war dann, dass ich multithreaded mehrere INSERT-/UPDATE-Operationen gleichzeitig gemacht habe.

Im obigen Artikel steht auch explizit:

it returns the value of an autoincrement column that is generated on the same connection.

Bei mir war es dann so, dass ich dieselbe Connection-Instanz hatte (weil MS Access kein Connection-Pooling unterstützt) und die INSERT-/UPDATE-Operationen sich überlappt hatten, quasi:

  1. INSERT-SQL A ausführen.
  2. INSERT SQL B ausführen.
  3. Identity für SQL A holen.
  4. Identity für SQL B holen.

Dann kamen die falschen Ergebnisse zurück.

Ich habe dann via lock-Statement dafür gesorgt, dass ein INSERT samt Identität-Holen eine Einheit bildet, so dass es dann so ablief:

  1. INSERT-SQL A ausführen.
  2. Identity für SQL A holen.
  3. INSERT SQL B ausführen.
  4. Identity für SQL B holen.

Bisher hat das sauber funktioniert.

Sonderfall VistaDB

Nach meinem Verständnis gilt das auch für VistaDB, falls dort die Connection nicht sofort wieder geschlossen wird, sondern von verschiedenen Abfragen wiederverwendet wird.

Die Dokumentation schreibt:

@@IDENTITY
Returns the last inserted identity value (scoped by session).

In dem Fall sollte dann auch auf VistaDB so wie oben bei MS Access beschrieben, synchronisiert werden.

Allerdings unterstützt VistaDB das Connection-Pooling, so dass das eigentlich gar nicht nötig sein sollte.