Parrelitätsverletzung / MS - SQL



  • Task ist eine Klasse die einfach Werte beinhaltet und in einer Datenbank schon
    gespeichert wurden. Nun möchte ich diesen "Task" updaten dafür suche ich als
    erstes in der Datenbank nach der ID die der Task besitzt. Danach gebe ich die
    Row weiter an FillRowWithTaskValues, die diesen Row dann mit den Werten
    befüllt. Danach ein einfaches Update doch da entsteht immer folgender Fehler:
    Parallelitätsverletzung : Der UpdateCommand hat sich auf 0 der erwarteten 1
    Datensätze ausgewirkt. Ich vermute das er diesen Row gar nicht verändert und
    das wenn keine Veränderungen bestehen er mir diesen Fehler ausgibt 😕
    Hier mal der Code:

    public void UpdateTask(Task task, DataSet dataSet, SqlDataAdapter adapter, String database)
            {
                //Search the max ID
                int maxIdSort = SearchMaxID(dataSet, database);
                //Search the Position from the Task
                int rowPosition = 0;
                foreach(DataRow row in dataSet.Tables[database].Rows)
                {
                    if ((int)row["ID"] != task.Id)
                        rowPosition++;
                    else
                        break;
                }
                //Fill the row with the datas from the Task
                FillRowWithTaskValues(task, maxIdSort, dataSet.Tables[database].Rows[rowPosition]);
                SqlCommandBuilder cmb = new SqlCommandBuilder(adapter);
                //Update database
                adapter.Update(dataSet.Tables[database]);
            }
    
    private static void FillRowWithTaskValues(Task task, int maxIdSort, DataRow row) 
            {
                row.BeginEdit();
                row["User"] = task.User;
                row["Done"] = task.Done;
                row["Text"] = task.Text;
                row["TitleText"] = task.TitleText;
                row["Header"] = task.Header;
                row["CreateDate"] = task.CreateDate;
                row["SizeWidth"] = task.Size.Width;
                row["SizeHeight"] = task.Size.Height;
                row["X"] = task.Location.X;
                row["Y"] = task.Location.Y;
                row["FontName"] = task.Font.Name;
                row["Bold"] = task.Font.Bold;
                row["Italic"] = task.Font.Italic;
                row["FontSize"] = task.Font.Size;
                row["TitleFontName"] = task.TitleFont.Name;
                row["TitleBold"] = task.TitleFont.Bold;
                row["TitleItalic"] = task.TitleFont.Italic;
                row["TitleFontSize"] = task.TitleFont.Size;
                row["TaskColor"] = task.TaskColor.ToArgb();
                row["TitleTextColor"] = task.TitleTextColor.ToArgb();
                row["TitleColor"] = task.TitleColor.ToArgb();
                row["TextBackgroundColor"] = task.TextBackgroundColor.ToArgb();
                row["TextColor"] = task.TextColor.ToArgb();
                row["BorderSize"] = task.BorderSize;
                row["TitleDistance"] = task.TitleDistance;
                row["ID_Sort"] = maxIdSort;
                row["Edit"] = task.Edit;
                row.EndEdit();
            }
    

    Wisst ihr vielleicht woran es liegt? Ich hoff der Code ist leserlich.

    Danke



  • Problem gefunden:

    cmb.ConflictOption = ConflictOption.OverwriteChanges;
    

    musste ich noch mit einfügen. Fehler behoben 🙂

    Aber mich würde trodzdem gern interessieren wieso ich eine Parallelitätsverletzung verursacht habe.

    Danke



  • Frager schrieb:

    Fehler behoben 🙂

    Guter Scherz, von wegen!

    Das Problem ist, dass die originalen Datensätze Deiner DataTable in der Datenbank geändert haben. Sprich: Irgendwer oder irgendwas hat eine Änderung an dem Datensatz vorgenommen den Du aktualisieren willst - das ist Parallelitätsverletzung. Mit den ConflictOptions ignorierst Du das Problem nur und überschreibst die Änderungen in der DB. Wenn Dein Programm ein Mehrbenutzersystem ist dann Prost Mahlzeit, wenn Du das so einsetzen willst. Wenn Du SQL 2005 einsetzt, dann schaue Dir mal die SQL-Notifications an, aber Achtung, das ist eher was für Serverprogramme!



  • SeboStone schrieb:

    Frager schrieb:

    Fehler behoben 🙂

    Guter Scherz, von wegen!

    Das Problem ist, dass die originalen Datensätze Deiner DataTable in der Datenbank geändert haben. Sprich: Irgendwer oder irgendwas hat eine Änderung an dem Datensatz vorgenommen den Du aktualisieren willst - das ist Parallelitätsverletzung. Mit den ConflictOptions ignorierst Du das Problem nur und überschreibst die Änderungen in der DB. Wenn Dein Programm ein Mehrbenutzersystem ist dann Prost Mahlzeit, wenn Du das so einsetzen willst. Wenn Du SQL 2005 einsetzt, dann schaue Dir mal die SQL-Notifications an, aber Achtung, das ist eher was für Serverprogramme!

    oh 😮 das heißt das seit dem letzten Aktualisierung meines DataTables im Programm sich der Originale Datensatz in der Datenbank sich bereits geändert hat?
    Wenn ja welche folgen könnten es sich da nach sich ziehen wenn ich diesen Fehler ignoriere?

    Danke



  • Ja genau!

    Wie bereits geschrieben, Du überschreibst die in der Datenbank gemachten Änderungen, die sind dann einfach mal weg.



  • Ok alles klar ich werde einfach das DataTable vor dem TaskUpdate die DataTable aktualisiere. Müsste so behoben seien, oder? Mit Notifiy möchte ich mich erstmal noch nicht auseinandersetzen.

    Danke für deine Hilfe 🙂



  • Das lässt sich so pauschal nicht sagen. Zwischen dem Neubefüllen Deines DataSets und Deines tatsächlichen Updates vergeht ebenfalls Zeit in der jemand anderes Änderungen durchführen kann. Nur wenn Du einen Lock auf die Datensätze legst (was ein super performancekiller sein kann) kannst Du sicher sein, dass sie nicht geändert werden bevor Du Deine Änderungen eingespielt hast.



  • Hm locks sind Riskant in meinen Programm da es schnell sein muss, und desweiteren wegen den Deadlocks. Ich hab es über diesen weg gelöst das ich direkt

    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; BEGIN TRANSACTION; UPDATE EDIT = TRUE WHERE ID = 0 COMMIT TRANSACTION;

    An die Datenbank gebe und immer überprüfe ob er bearbeitet wird. 🙂 Habe es auch gerade ausprobiert mit 2 rechnern die fast gleichzeitig einen Task Updaten. Der eine PC wurde geblockt der andere hatte zugriff. Ich hoff das, dass eine saubere lösung war. 😉 wenn nicht bitte bescheid sagen.

    Danke dir Sebo



  • Das Problem besteht immer noch. Da Du nur ein Update-Kommando ausführst ist die Transaktion überflüssig, bzw. bringt nix ausser Zeitverlust.

    Um eine Parallelitätsverletzung noch mal genau zu skizzieren:

    time | task 1 | task 2
    ----------------------------
    1 | lesen | --
    2 | -- | lesen
    3 | schreiben | --
    4 | -- | schreiben

    Du versuchst zum Zeitpunkt 4 zu schreiben, dabei ist es völlig egal ob Du den Zeitpunkt 4 in eine Transaktion packst oder nicht, bringt nix. Wenn Du's mit Transaktionen lösen willst, dann packe für task 2 den Zeitpunkt 2 + 4 in eine Transaktion, für task 1 den Zeitpunkt 1 + 3 in eine Transaktion.


Anmelden zum Antworten