Laden...

Primary Key nach Update erhalten

Erstellt von -Hades- vor 10 Jahren Letzter Beitrag vor 10 Jahren 2.444 Views
-
-Hades- Themenstarter:in
171 Beiträge seit 2007
vor 10 Jahren
Primary Key nach Update erhalten

verwendetes Datenbanksystem: MySql

Hallo,

ich schreibe zur Zeit an einem Programm welches eine MySql-Datenbank nutzt. Ich verwende Visual Studio 2012 und nutze stark typisierte Datasets, da dies der bequemste Weg zu sein scheint.

Ich habe für alle Tabellen einen Primärschlüssel mit AutoIncrement-Attribut. Wenn ich ein Dataset, in dem ich mehrere Zeilen eingefügt habe mit Hilfe des TableAdapters in die Datenbank einfüge (Update-Methode), werden die Zeilen im Dataset nicht mit dem von der Datenbank vergebenen Primärschlüssel aktualisiert.

Die Werte brauche ich allerdings um Zuordnungen zu machen. Wenn ich zwei Zeilen mit gleichen Werten einfüge (theoretisch) kann ich ja auch nicht einfach nach den Werten in der DB suchen um den vergebenen Wert zu erhalten, außerdem ist das ja nicht unbedingt sehr performant.
Ich würde die Update-Commands auch ungerne umschreiben, da diese dann ja bei der nächsten Änderung der Datenbank überschrieben werden da der Code generiert wird.

Meine Frage also: Gibt es eine Einstellung, so dass die Zeilen des Dataset nach dem Update aktualisiert werden? (Wird der return der Kennung von MySql vielleicht gar nicht unterstützt?)
Wenn dem nicht so ist was würdet ihr vorschlagen? Ich denke ich würde mir dann eine eigene Kennung über GUID erzeugen, da mir das als die einfachste und eine funktionierende Lösung vorkommt.

Ich bin für alle nicht umständlichen Lösungen und Vorschläge offen. 😉

-Hades-

16.834 Beiträge seit 2008
vor 10 Jahren

Ich denke ich würde mir dann eine eigene Kennung über GUID erzeugen

Das würde ich auch tun, allein aus dem Grund wie Dein Workflow gestaltet ist. Du brauchst die ID direkt -> also erzeug sie im Client -> Client sollten als Key aber nur GUIDs erzeugen

M
184 Beiträge seit 2012
vor 10 Jahren

ansonsten kannst du die letzte ID über einen eigenen Query abfragen

SELECT LAST_INSERT_ID();

Ob der MySQL-Provider für .NET das schon irgendwie implementiert, kann ich dir leider nicht sagen.

F
10.010 Beiträge seit 2004
vor 10 Jahren

Da das typisierte DS auch nur ein DS ist, kannst du im RowUpdated Event die neue ID per "SELECT LAST_INSERT_ID()" abfragen und setzen.

-
-Hades- Themenstarter:in
171 Beiträge seit 2007
vor 10 Jahren

Hi FZelle,

also das mit dem Event hört sich an sich nicht schlecht an, jedoch frage ich mich ob das praktikabel ist. Die Sache ist, das ich nicht immer für jede Zeile im Dataset ein Update aufrufe, sondern ein Update für ein ganzes Dataset, in dem ich mehrere Zeilen geaddet habe.
Ich kann ja jetzt nicht garantieren das der "SELECT LAST_INSERT_ID()" Befehl genau die ID zu der Zeile für die ich gerade das Event behandle zurück liefert. Es kann ja in der Zeit in der das Event behandelt wird schon wieder eine neue Zeile geschrieben sein.?

Falls es doch einen Mechzanismus gibt mit dem ich in dem UpdateEvent genau die ID zu der Zeile bekomme wäre das natürlich besser.
Ansonsten würde ich dann jetzt die GUID´s einsetzen.

F
10.010 Beiträge seit 2004
vor 10 Jahren

Solltest Du irgendwann mal die Doku zu RowUpdated durchlesen, so wirst du feststellen das es eben für jede einzelne Zeile beim Update aufgerufen wird.

-
-Hades- Themenstarter:in
171 Beiträge seit 2007
vor 10 Jahren

Hmm ja das ist klar FZelle,

aber was passiert wenn ich 1000 Zeilen in meinem Dataset hinzugefügt habe und für das Dataset jetzt über den TableAdapter committe und in die Datenbank schreibe.
Dann wird, wie du schon gesagt hast, das RowChanged-Ereignis für jede Zeile ausgeführt.
Ist denn jetzt garantiert, dass wenn ich per SELECT LAST_INSERT_ID() die ID hole das auch diejenige für genau die Zeile ist die ich in dem Event behandle?
Das DBMS wird ja kaum warten bis ich mein Event behandelt habe bevor es die nächste Zeile einfügt.

Ich hoffe es ist verständlich was ich meine.
Wenn in den Ereignisparametern schon die zurückgeliferte ID drin stehen würde wäre das kein Problem aber da habe ich ja nur den EreignisTyp (Commit)...

-
-Hades- Themenstarter:in
171 Beiträge seit 2007
vor 10 Jahren

Um das Problem nochmal zu verdeutlichen: Nehmen wir an ich habe nicht nur einen Client der sein Dataset committed, sondern 1000 Clients die alle gleichzeitig ihre Datasets in die Datenbank schreiben lassen.
Jetzt muss ich in dem Event für jede Zeile garantieren können, dass Select last insert id auch genau die richtige ID für genau die behandelte Zeile liefert, ansonsten ist das nutzlos.

M
184 Beiträge seit 2012
vor 10 Jahren

Den Wert für "LAST_INSERT_ID" merkt sich MySQL Verbindungsspezifisch. Das heißt wenn du mit der gleichen Connection den Wert abfragst, wird für dich die ID des letzten Inserts oder Updates einer Auto_increment-Spalte ermittelt.

So könnte es wohl z.B. aussehen:
Du feuerst in deinem DS ein Commit ab.
ADO.NET macht jetzt für jeden eingefügten Datensatz ein Insert
Nach jedem Insert wird das Event RowUpdated gefeuert
dort fragst du mit der selben Connection die ID ab

Ich habe es selbst aber noch nie ausprobiert 😉

-
-Hades- Themenstarter:in
171 Beiträge seit 2007
vor 10 Jahren

Ah ok,

das hört sich gut an, dann werde ich das wohl mal in einem Stresstest ausprobieren.

Falls das schonmal jemand getestet hat oder definitiv weiß das es funktioniert, bitte melden.

F
10.010 Beiträge seit 2004
vor 10 Jahren

Was meinst Du weshalb wir das hier jedesmal antworten wenn jemand so etwas fragt, oder warum das in der Doku exakt so beschrieben steht?

W
955 Beiträge seit 2010
vor 10 Jahren

Willst Du nicht lieber erst einmal schauen ob es ein Treiber gibt der das für Dich macht? Evtl einen kostenpflichtigen wie Devart oder eine andere Version? Das Stempeln angefügter Sätze beim Speichern sollte doch eigentlich der Treiber können.

F
10.010 Beiträge seit 2004
vor 10 Jahren

Nein, warum soll er das machen?

EF oder andere ORMapper machen das, aber nicht das DataSet.
Und da ist dies exakt was MS vorsieht.

R
74 Beiträge seit 2006
vor 10 Jahren

Nein, warum soll er das machen?

EF oder andere ORMapper machen das, aber nicht das DataSet.
Und da ist dies exakt was MS vorsieht.

Das MySQL Client-Server Protokoll macht das schon. Der Treiber
müsste also nur die Serverantwort nach einem Insert auswerten.

Aufwand = NULL.

Nach einem INSERT (...) [ON DUPLICATE KEY ...]

liefert der Server AffectedRows = 2 für Update, AffectedRows = 1 für Insert
und die ID des betroffenen Datensatzes bei Update bzw. die neue ID bei Insert.

Dazu braucht man kein kostenpflichtigen Treiber sondern nur die zur Verfügung
stehenden Bibliotheken.

Hoffe geholfen zu haben.