Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Primary Key nach Update erhalten
-Hades-
myCSharp.de - Member



Dabei seit:
Beiträge: 171
Herkunft: Deutschland NRW

Themenstarter:

Primary Key nach Update erhalten

beantworten | zitieren | melden

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-
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.931

beantworten | zitieren | melden

Zitat von -Hades-
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
private Nachricht | Beiträge des Benutzers
MorphieX
myCSharp.de - Member



Dabei seit:
Beiträge: 184
Herkunft: Rahden

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 9.977

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
-Hades-
myCSharp.de - Member



Dabei seit:
Beiträge: 171
Herkunft: Deutschland NRW

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 9.977

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
-Hades-
myCSharp.de - Member



Dabei seit:
Beiträge: 171
Herkunft: Deutschland NRW

Themenstarter:

beantworten | zitieren | melden

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)...
private Nachricht | Beiträge des Benutzers
-Hades-
myCSharp.de - Member



Dabei seit:
Beiträge: 171
Herkunft: Deutschland NRW

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
MorphieX
myCSharp.de - Member



Dabei seit:
Beiträge: 184
Herkunft: Rahden

beantworten | zitieren | melden

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 ;-)
private Nachricht | Beiträge des Benutzers
-Hades-
myCSharp.de - Member



Dabei seit:
Beiträge: 171
Herkunft: Deutschland NRW

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 9.977

beantworten | zitieren | melden

Was meinst Du weshalb wir das hier jedesmal antworten wenn jemand so etwas fragt, oder warum das in der Doku exakt so beschrieben steht?
private Nachricht | Beiträge des Benutzers
witte
myCSharp.de - Member



Dabei seit:
Beiträge: 955

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 9.977

beantworten | zitieren | melden

Nein, warum soll er das machen?

EF oder andere ORMapper machen das, aber nicht das DataSet.
Und da ist dies exakt was MS vorsieht.
private Nachricht | Beiträge des Benutzers
RED-BARON
myCSharp.de - Member



Dabei seit:
Beiträge: 74

beantworten | zitieren | melden

Zitat von FZelle
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.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von RED-BARON am .
private Nachricht | Beiträge des Benutzers