Laden...

Wie kann ich die ID eines neuen Datensatzes herausfinden?

Erstellt von Rumtscho vor 16 Jahren Letzter Beitrag vor 16 Jahren 2.565 Views
R
Rumtscho Themenstarter:in
11 Beiträge seit 2007
vor 16 Jahren
Wie kann ich die ID eines neuen Datensatzes herausfinden?

Hallo,

Ich mache eine kleine ASP .NET Anwendung, die Daten halte ich in einer Access 2003 Datenbank. Die IDs in der Datenbank sind AutoWert. Ich will ein neues Objekt vom Typ Workflow erstellen, seine Daten in der DB speichern, und später Objekte vom Typ WorkflowStep zu meinem Workflow erstellen, und diese auch speichern. Das Erstellen von WorkflowStep Objekten, die einen Workflow referenzieren ist natürlich kein Problem, aber um die Referenz in die DB zu speichern, brauche ich die ID des Datensatzes, in dem das Workflow Objekt gespeichert ist. Im Moment mache ich das mit einer Funktion, die die höchste ID zurückgibt:


private int writeWorkflowIntoDb()
{
    System.Data.OleDb.OleDbCommand cmd= new System.Data.OleDb.OleDbCommand();
    try
    {
        cmd.Connection = DBConnector.Conn;
        cmd.CommandText = string.Format("INSERT INTO Workflow (Name) VALUES ('{0}');", newName);
        cmd.ExecuteNonQuery();
        cmd.CommandText = "SELECT MAX(ID) FROM Workflow";
        Object newID = cmd.ExecuteScalar();
        int ret = (int) newID;
        return ret;
    }
    finally
    {
        cmd.Dispose();
        DBConnector.Close();
    }
}

(erste Abfrage vereinfacht zur besseren Lesbarkeit)

Damit habe ich aber ein Problem. Eine Web Anwendung hat ja mehrere Benutzer gleichzeitig. Und falls zwei davon gleichzeitig einen Workflow erstellen, kann vorkommen, dass zuerst der eine Workflow geschrieben wird, dann der Zweite, und erst dann die höchste ID gelesen wird. Dann wird aber zwei Mal die ID des zweiten zurückgegeben, was offensichtlich dazu führen wird, dass später die Steps, die zum ersten gehören, in der DB den zweiten referenzieren. Wie kann ich das Problem lösen? Ich vermute, dass es für so ein Standardproblem auch eine Standardlösung gibt, aber mir fehlt eine formale Ausbildung in Programmieren.

432 Beiträge seit 2005
vor 16 Jahren

hi rumtscho,

aus diesem grunde verwendet man am besten den datentyp Guid ( = uniqueIdentifier im SQL Server) als Primärschlüssel.

es erlaubt der anwendung, die guid selbst zu erzeugen mit:


DataRow row = myDataTyble.Rows.Add();
row["RecordID"] = Guid.NewGuid();

und schon dann als verweis im dataset zu benutzen, noch bevor der datensatz physikalisch in der DB vorhanden ist.

deine lösung hat ja außerdem den Performance-Nachteil, dass du ja eigentlich "nur schonmal speicherst", um die ID überhaupt erst zu bekommen, die du dann zur Weiterverarbeitung brauchst.

hth,
ron

R
Rumtscho Themenstarter:in
11 Beiträge seit 2007
vor 16 Jahren

Hi Ron,
Eben aus Performance-Gründen verwende ich keine einzige DataTable in der ganzen Anwendung. Ich habe es schon mal erlebt, eine Anwendung hat eine DataTable mit 14000 Einträgen benutzt, und der haben 512 MB Hauptspeicher nicht ausgereicht. Dabei war die komplette Access Datenbank, die die Tabelle enthalten hat, nur 4 MB (!). Sobald wir die DataTable mit einem leeren Dummy ersetzt haben, brauchte die Anwendung nur noch 60 MB.
Bei mir wird alles gelesen und direkt in Objekte gespeichert. Und wenn ein neues Objekt erzeugt wird, wird es auch in die DB gespeichert. Auch wenn ich ein DataTable als Zwischenschicht verwenden würde, würde ich trotzdem sofort speichern wollen, denn wie soll ich es sonst machen? Sagen wir, ich würde alles in ein DataSet schreiben einmal pro Stunde die Änderungen aus dem DataSet in die DB schreiben. Dan muss ich mich erstmal darum sorgen, Änderungverfolgung zu machen, und zweitens, falls in dieser Stunde etwas passiert (z.B. Serverausfall), sind die Änderungen verloren. Das ist ärgerlich, und bei 20-50 Intranet Benutzer, die die Anwendung nutzen, speichere ich lieber sofort, auch wenn alle gleichzeitig eine Verbindung aufmachen, verkraftet es der Server.
Und die Access AutoWerte kann ich nicht mit einem .Net spezifischen ID ersetzen, weil ein Großteil der Daten nicht durch meine .NET Anwendung in die Datenbank eingegeben wird, sondern durch Access Formulare, und da gibt es kein Guid.

12 Beiträge seit 2006
vor 16 Jahren

Was mir mal geholfen hatte, war erstmal das herausnehmen der Auto-Werte aus der entsprechenden Tabelle und das Ausgeben von IDs über eine Sequenz.

Per Trigger wurde beim Einfügen kontrolliert, ob der Datensatz eine ID besitzt, wenn nicht, wurde die Sequenz (sofern Integer-Werte) benutzt.

Beim setzen einer ID aus dem Programm las ich die ID ebenfalls aus der Sequenz aus.

Somit konnten das Einfügen aus der DB und per App. sich nicht in die Quere kommen.

(ja|nein|vielleicht)*

F
10.010 Beiträge seit 2004
vor 16 Jahren

@Rumtscho:

Such mal nach "Select @@Identity".

R
Rumtscho Themenstarter:in
11 Beiträge seit 2007
vor 16 Jahren

FZelle,

Das war genau das was ich brauchte. 👍

Vielen Dank an Dir und an alle anderen, die Tips gegeben haben!