Benutzer mit den meisten Antworten
Parallelitätsverletzung

Frage
-
Halloich habe ein Schedule Control was über Databinding mit einer DataTable verbunden ist.Sobald ich im Control was ändere und ein Update auf den Adapter durchführe bekomme ich die unten stehende Meldung:{"Parallelitätsverletzung : Der UpdateCommand hat sich auf 0 der erwarteten 1 Datensätze ausgewirkt."}Was hat das zu bedeuten ? Kann mir jemand weiterhelfen, wie man das verhindert ?DankeAndreas
- Bearbeitet Robert BreitenhoferModerator Dienstag, 8. November 2011 12:45 Titel Korrektur: war =?iso-8859-1?Q?Parallelit=E4tsverletzung?=
Antworten
-
Hallo Andreas,
da dass Problem bei neuen Datenzeilen auftritt:
Wenn Du eine Tabelle mit Identitätswerten hast, so musst Du diese nach dem Einfügen getrennt abrufen,
da Access keine Batchbefehle unterstützt und somit kein Abruf des von Access vergebenen Identitätswerts erfolgt.Siehe dazu: Abrufen von Identitäts- oder AutoWert-Werten (ADO.NET)
insbes. den Abschnitt "Abrufen von Microsoft Access-AutoWert-Werten".Es empfiehlt sich bei der DataTable mit negativem AutoIncrementStep zu arbeiten,
damit keine Dopplungen auftreten (und man sieht, obe es sich um einen gespeicherten Satz handelt).Gruß Elmar
- Als Antwort vorgeschlagen Marcel RomaModerator Mittwoch, 9. November 2011 16:03
- Als Antwort markiert Robert BreitenhoferModerator Mittwoch, 16. November 2011 10:25
Alle Antworten
-
Hallo Andreas Waning,
Die aktuellste Version der Community Forums NNTP Bridge ist 2011-05-31, V44 (Stable): http://communitybridge.codeplex.com/releases/view/67354
Deine Version ist Community Forums NNTP Server 1.1.40.0
Grüße,
Robert
-
Hallo Andreas,
die Ausnahme kommt, wenn durch die Kriterien des UpdateCommand keinen Datensatz aktualisiert wurde,
siehe dazu Vollständige Parallelität (ADO.NET).Neben dem vorgesehen Fall, dass ein anderer Anwender den Datensatz aktualisiert hat,
kann es in einigen Datenkonstellationen ungewollt dazu kommen,
z. B. bei Gleitkommazahlen durch Ungenauigkeiten, die beim Konvertieren entstehen können.
Oder auch wenn das Datenbankschema nicht mehr ganz zur DataTable passt.Überprüfe mal die Kriterien, die das UpdateCommand verwendet.
Gruß Elmar
-
Hallo Andreas,
Elmar hat Recht. Unter Umständen erzeugt der Visual Studio Designer beim Erstellen einer neuen Datenquelle einen UpdateCommand-String für die vollständige Parallelität, der mit der verwendeten Storage-Datenbank nicht kompatibel ist. Schau mal in der XSD-Datei oder im DataSet-Designer nach.
In diesem Fall empfiehlt sich, einfache Parallelität zu verwenden. Dazu ersetzt man im DataSet-Designer die beim Adapter erzeugte, ellenlange WHERE-Clause durch eine einfachere Variante, z.B. "WHERE (AppointmentID = ?)".Einen ähnlichen Fall (Parallelitätsverletzung mit Scheduling-Komponente) kannst Du hier finden:
http://www.devexpress.com/Support/Center/p/Q250535.aspxGruß
Marcel -
Hallo MArcel,das mit der Where Abfrage habe ich gemacht. Klappt trotzdem nicht.Keine Ahnung was der da hat. Ich versuch mal Infragistics ran zuziehen vielleicht hat der eine Lösung.Danke,Andreas"Marcel Roma" schrieb im Newsbeitrag news:6fa307ab-9559-4e64-ae63-d0455af3313c@communitybridge.codeplex.com...
Hallo Andreas,
Elmar hat Recht. Unter Umständen erzeugt der Visual Studio Designer beim Erstellen einer neuen Datenquelle einen UpdateCommand-String für die vollständige Parallelität, der mit der verwendeten Storage-Datenbank nicht kompatibel ist. Schau mal in der XSD-Datei oder im DataSet-Designer nach.
In diesem Fall empfiehlt sich, einfache Parallelität zu verwenden. Dazu ersetzt man im DataSet-Designer die beim Adapter erzeugte, ellenlange WHERE-Clause durch eine einfachere Variante, z.B. "WHERE (AppointmentID = ?)".Einen ähnlichen Fall (Parallelitätsverletzung mit Scheduling-Komponente) kannst Du hier finden:
http://www.devexpress.com/Support/Center/p/Q250535.aspxGru�?
Marcel -
Hallo Andreas,
das Steuerelement hat damit i. a. nichts zu tun -
ausgenommen es arbeitet bei der Datenbindung unsauber.Die Antwort war wiederum nur sehr allgemein, da Du weder zur verwendeten Datenbank
noch zum Tabellenschema und generierten UpdateCommand näheres gesagt hast.Wenn selbst das von Marcel vorgeschlagene Nur-PK-Update (Last-Wins) fehlschlägt,
so wäre eine Frage: Welcher Datentyp haben die Primärschlüsselspalten?Wenn Du dazu mehr Infos hast, kann man das Problem eher einkreisen.
Gruß Elmar
-
Hallo Elmar,danke für deine Hilfe.Dem Steuerelement wird ein Appointment zugewiesen. Das wird angezeigt und bei UpdateDatatable auch gespeichert. Nur wenn ich jetzt das Appointment verändere und dann versuche zu speichernkommt der Fehler. (Das hat nichts mit 2 Benutzer zutun.) Alle anderen Appointment, ausser dem neu zugefügten, kann ich speichern.Wenn ich die App neu starte, dann kann ich dieses Appointment verändern und speichern.Das Update habe ich so wie Marcel meinte mal abgeändert. (Where Appentmentid = ?) Der Fehler tritt dann immer noch auf.Keine Ahnung was ich da noch machen soll.Danke für eure Hilfe,AndreasHier die Tabelle: (Accesstabelle)AppointmentID ist der primary key vom typ int (Autowert)AppointmentID AllProperties StartDateTime EndDateTime Subject AllDayEvent OwnerKey
1 02.11.2011 08:00:00 02.11.2011 10:00:00 Ortstermin1 Nein AW
2 02.11.2011 08:00:00 02.11.2011 09:45:00 Aktenbearbeitet Nein MW
3 14.11.2011 08:00:00 14.11.2011 12:45:00 AW Nein AW
5 14.11.2011 13:00:00 14.11.2011 14:00:00 New Appointment Nein MWHier das Update command:// Configure the UPDATE command
OleDbCommand updateCommand = new OleDbCommand();
commandTextTemplate = @"UPDATE {0} SET AllDayEvent = ?, AllProperties = ?, EndDateTime = ?, OwnerKey = ?, StartDateTime = ?, Subject = ? WHERE (AppointmentId = ?) AND (AllDayEvent = ?) AND (AllProperties = ? OR ? IS NULL AND AllProperties IS NULL) AND (EndDateTime = ?) AND (OwnerKey = ? OR ? IS NULL AND OwnerKey IS NULL) AND (StartDateTime = ?) AND (Subject = ? OR ? IS NULL AND Subject IS NULL)";
updateCommand.CommandText = string.Format( commandTextTemplate, WinScheduleMSAccessSupport.APPOINTMENTS_TABLE_NAME );
updateCommand.Connection = this.Connection;
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("AllDayEvent", System.Data.OleDb.OleDbType.Boolean, 2, "AllDayEvent"));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("AllProperties", System.Data.OleDb.OleDbType.VarBinary, 0, "AllProperties"));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("EndDateTime", System.Data.OleDb.OleDbType.DBTimeStamp, 0, "EndDateTime"));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("OwnerKey", System.Data.OleDb.OleDbType.VarWChar, 50, "OwnerKey"));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("StartDateTime", System.Data.OleDb.OleDbType.DBTimeStamp, 0, "StartDateTime"));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("Subject", System.Data.OleDb.OleDbType.VarWChar, 50, "Subject"));
//updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("AppointmentId", System.Data.OleDb.OleDbType.Integer,0,"AppointmentId"));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_AppointmentId", System.Data.OleDb.OleDbType.Integer, 0, System.Data.ParameterDirection.Input, false, ((System.Byte)(10)), ((System.Byte)(0)), "AppointmentId", System.Data.DataRowVersion.Original, null));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_AllDayEvent", System.Data.OleDb.OleDbType.Boolean, 2, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "AllDayEvent", System.Data.DataRowVersion.Original, null));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_AllProperties", System.Data.OleDb.OleDbType.VarBinary, 0, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "AllProperties", System.Data.DataRowVersion.Original, null));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_AllProperties1", System.Data.OleDb.OleDbType.VarBinary, 0, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "AllProperties", System.Data.DataRowVersion.Original, null));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_EndDateTime", System.Data.OleDb.OleDbType.DBTimeStamp, 0, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "EndDateTime", System.Data.DataRowVersion.Original, null));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_OwnerKey", System.Data.OleDb.OleDbType.VarWChar, 50, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "OwnerKey", System.Data.DataRowVersion.Original, null));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_OwnerKey1", System.Data.OleDb.OleDbType.VarWChar, 50, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "OwnerKey", System.Data.DataRowVersion.Original, null));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_StartDateTime", System.Data.OleDb.OleDbType.DBTimeStamp, 0, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "StartDateTime", System.Data.DataRowVersion.Original, null));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_Subject", System.Data.OleDb.OleDbType.VarWChar, 50, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "Subject", System.Data.DataRowVersion.Original, null));
updateCommand.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_Subject1", System.Data.OleDb.OleDbType.VarWChar, 50, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "Subject", System.Data.DataRowVersion.Original, null));
this._oleDbDataAdapterForAppointments.UpdateCommand = updateCommand;
"Elmar Boye [MVP]" schrieb im Newsbeitrag news:84af2a4c-285e-45ff-9158-cf3734b3f5e1@communitybridge.codeplex.com...Hallo Andreas,
das Steuerelement hat damit i. a. nichts zu tun -
ausgenommen es arbeitet bei der Datenbindung unsauber.Die Antwort war wiederum nur sehr allgemein, da Du weder zur verwendeten Datenbank
noch zum Tabellenschema und generierten UpdateCommand näheres gesagt hast.Wenn selbst das von Marcel vorgeschlagene Nur-PK-Update (Last-Wins) fehlschlägt,
so wäre eine Frage: Welcher Datentyp haben die Primärschlüsselspalten?Wenn Du dazu mehr Infos hast, kann man das Problem eher einkreisen.
Gru�? Elmar
-
Hallo Andreas,
Ich konnte das von dir gemeldete Verhalten mit der Scheduler-Komponente von Infragistics und einer Access-Datenbank beim besten Willen nicht nachvollziehen.
Selbst bei Anwendung von vollständiger Parallelität funktionierte das Ändern und das erneute Speichern ohne Zwischenfälle. Schwer zu sagen, was bei dir anders ist (OleDB z.B. ist sehr empfindlich gegenüber positionellen Änderungen der Parameter).
Nimm doch mal bitte die Standard-Demo (StartupSolution), die mit den WindowsForms-Komponenten von Infragistics kommt und binde z.B. das UltraDayView-Steuerelement an deine Access Datenbank. Teste ob folgender Code funktioniert:private void BindingDayView_Load(object sender, EventArgs e) { this.ultraCalendarInfo1.DataBindingsForAppointments.BindingContextControl = this; this.ultraCalendarInfo1.DataBindingsForAppointments.BindingContextControl = this; ds = new Data.schedulerDataSet(); appointmentAdapter = new AppointmentTableAdapter(); appointmentAdapter.Fill(ds.Appointment); // TODO:1. Set the DataSource and DataMember for Appointments using the SetDataBinding method this.ultraCalendarInfo1.DataBindingsForAppointments.SetDataBinding(ds, "Appointment"); this.ultraCalendarInfo1.DataBindingsForOwners.SetDataBinding(ds, "Owner"); // TODO:2. Set the properties for AppointmentsDataBinding and OwnersDataBinding objects this.ultraCalendarInfo1.DataBindingsForAppointments.StartDateTimeMember = "StartDateTime"; this.ultraCalendarInfo1.DataBindingsForAppointments.EndDateTimeMember = "EndDateTime"; this.ultraCalendarInfo1.DataBindingsForAppointments.SubjectMember = "Subject"; this.ultraCalendarInfo1.DataBindingsForAppointments.OwnerKeyMember = "OwnerKey"; this.ultraCalendarInfo1.DataBindingsForOwners.KeyMember = "OwnerKey"; this.ultraCalendarInfo1.DataBindingsForOwners.NameMember = "Name"; // TODO:3. Assign UltraCalendarInfo component to the CalendarInfo property of UltraDayView control. this.ultraDayView1.CalendarInfo = this.ultraCalendarInfo1; }
Wenn Du noch immer Probleme hast, lade bitte das von dir modifizierte StartupSolution-Projekt z.B. auf SkyDrive hoch und poste hier einen Link.Es wird sich ganz bestimmt eine Lösung auch für dein Problem finden. Das wäre doch gelacht ;-)
Gruß
Marcel -
Hallo Andreas,
da dass Problem bei neuen Datenzeilen auftritt:
Wenn Du eine Tabelle mit Identitätswerten hast, so musst Du diese nach dem Einfügen getrennt abrufen,
da Access keine Batchbefehle unterstützt und somit kein Abruf des von Access vergebenen Identitätswerts erfolgt.Siehe dazu: Abrufen von Identitäts- oder AutoWert-Werten (ADO.NET)
insbes. den Abschnitt "Abrufen von Microsoft Access-AutoWert-Werten".Es empfiehlt sich bei der DataTable mit negativem AutoIncrementStep zu arbeiten,
damit keine Dopplungen auftreten (und man sieht, obe es sich um einen gespeicherten Satz handelt).Gruß Elmar
- Als Antwort vorgeschlagen Marcel RomaModerator Mittwoch, 9. November 2011 16:03
- Als Antwort markiert Robert BreitenhoferModerator Mittwoch, 16. November 2011 10:25
-
Hallo Elmar,
Es ist sehr wahrscheinlich, dass Andreas in die von dir genannte Falle getappt ist. Wenn er einen vom Designer erstellten Adapter verwendet, steht die AppointmentID nach dem ersten Aufruf von Update() auf -N (z.B. -1), beim anschließenden Bearbeiten des gleichen Datensatzes und einem erneuten Aufruf von Update() wird die Parallelität verletzt, da natürlich kein Termin mit AppointmentID -1 gefunden werden kann.
Gruß
Marcel -
Hallo MArcelich werde das heute Abend oder morgen testen.Erstmal danke,Andreas"Marcel Roma" schrieb im Newsbeitrag news:f4614e0a-24a4-4a76-8255-1bd20118f6bd@communitybridge.codeplex.com...
Hallo Andreas,
Ich konnte das von dir gemeldete Verhalten mit der Scheduler-Komponente von Infragistics und einer Access-Datenbank beim besten Willen nicht nachvollziehen.
Selbst bei Anwendung von vollständiger Parallelität funktionierte das �?ndern und das erneute Speichern ohne Zwischenfälle. Schwer zu sagen, was bei dir anders ist (OleDB z.B. ist sehr empfindlich gegenüber positionellen �?nderungen der Parameter).
Nimm doch mal bitte die Standard-Demo (StartupSolution), die mit den WindowsForms-Komponenten von Infragistics kommt und binde z.B. das UltraDayView-Steuerelement an deine Access Datenbank. Teste ob folgender Code funktioniert:private void BindingDayView_Load(object sender, EventArgs e) { this.ultraCalendarInfo1.DataBindingsForAppointments.BindingContextControl = this; this.ultraCalendarInfo1.DataBindingsForAppointments.BindingContextControl = this; ds = new Data.schedulerDataSet(); appointmentAdapter = new AppointmentTableAdapter(); appointmentAdapter.Fill(ds.Appointment); // TODO:1. Set the DataSource and DataMember for Appointments using the SetDataBinding method this.ultraCalendarInfo1.DataBindingsForAppointments.SetDataBinding(ds, "Appointment"); this.ultraCalendarInfo1.DataBindingsForOwners.SetDataBinding(ds, "Owner"); // TODO:2. Set the properties for AppointmentsDataBinding and OwnersDataBinding objects this.ultraCalendarInfo1.DataBindingsForAppointments.StartDateTimeMember = "StartDateTime"; this.ultraCalendarInfo1.DataBindingsForAppointments.EndDateTimeMember = "EndDateTime"; this.ultraCalendarInfo1.DataBindingsForAppointments.SubjectMember = "Subject"; this.ultraCalendarInfo1.DataBindingsForAppointments.OwnerKeyMember = "OwnerKey"; this.ultraCalendarInfo1.DataBindingsForOwners.KeyMember = "OwnerKey"; this.ultraCalendarInfo1.DataBindingsForOwners.NameMember = "Name"; // TODO:3. Assign UltraCalendarInfo component to the CalendarInfo property of UltraDayView control. this.ultraDayView1.CalendarInfo = this.ultraCalendarInfo1; }
Wenn Du noch immer Probleme hast, lade bitte das von dir modifizierte StartupSolution-Projekt z.B. auf SkyDrive hoch und poste hier einen Link.Es wird sich ganz bestimmt eine Lösung auch für dein Problem finden. Das wäre doch gelacht ;-)
Gru�?
Marcel -
Hallo Elmar,erstmal danke,ich schaue mir das später in ruhe an.
"Elmar Boye [MVP]" schrieb im Newsbeitrag news:c4aacafc-a78f-4cd0-9f39-ac0295b60ab0@communitybridge.codeplex.com...Hallo Andreas,
da dass Problem bei neuen Datenzeilen auftritt:
Wenn Du eine Tabelle mit Identitätswerten hast, so musst Du diese nach dem Einfügen getrennt abrufen,
da Access keine Batchbefehle unterstützt und somit kein Abruf des von Access vergebenen Identitätswerts erfolgt.Siehe dazu: Abrufen von Identitäts- oder AutoWert-Werten (ADO.NET)
insbes. den Abschnitt "Abrufen von Microsoft Access-AutoWert-Werten".Es empfiehlt sich bei der DataTable mit negativem AutoIncrementStep zu arbeiten,
damit keine Dopplungen auftreten (und man sieht, obe es sich um einen gespeicherten Satz handelt).Gru�? Elmar
-
Hast du den Infragistcs Form 11.1 ?Ich würde dir das dann auf dropbox legen, so das du das laden kannst.Hier beim Kunden kann ich leider kein Dropbox !!!"Marcel Roma" schrieb im Newsbeitrag news:677febc4-907e-491f-bf5d-10a13d127e6e@communitybridge.codeplex.com...
Hallo Elmar,
Es ist sehr wahrscheinlich, dass Andreas in die von dir genannte Falle getappt ist. Wenn er einen vom Designer erstellten Adapter verwendet, steht die AppointmentID nach dem ersten Aufruf von Update() auf -N (z.B. -1), beim anschlie�?enden Bearbeiten des gleichen Datensatzes und einem erneuten Aufruf von Update() wird die Parallelität verletzt, da natürlich kein Termin mit AppointmentID -1 gefunden werden kann.
Gru�?
Marcel -
Hallo Andreas,
> Hast du den Infragistcs Form 11.1?
Ja> Ich würde dir das dann auf dropbox legen, so das du das laden kannst.
Poste bitte den Link dazu.Gruß
Marcel- Bearbeitet Marcel RomaModerator Mittwoch, 9. November 2011 18:38 HTML-Editor spinnt
-
Da bin ich ja mal gespannt ob dir dazu was einfällt.Im Menu Data -> Save kannst du ein Update ausführen. (Hab ich hinzugefügt)Gehe folgendermassen vor:-lege ein neues Appointment an. (Click in Slot)-Speiche im Menu Save-ändere die Zeit durch ziehen des Slots.-Speiche wieder.Irgendwann bekommt zu eine Fehlermeldung. Dann kann dieses Appointment nicht mehr gespeichert werden.Danke,Andreas
"Marcel Roma" schrieb im Newsbeitrag news:25bf6af7-ba0f-41d5-82eb-2a0e80191502@communitybridge.codeplex.com...Hallo Andreas,
> Hast du den Infragistcs Form 11.1?
Ja> Ich würde dir das dann auf dropbox legen, so das du das laden kannst.
Poste bitte den Link dazu.Gru�?
Marcel -
Hallo Marcel,was ich vergessen hatte. Die Accessdatei liegt im DebugVerzeichnis. Du brauchst nur das File entpacken. Du brauchst nichts an Pathen einstellen.Bin mal gespannt was du da rausfindest.Danke,Andreas
"Marcel Roma" schrieb im Newsbeitrag news:25bf6af7-ba0f-41d5-82eb-2a0e80191502@communitybridge.codeplex.com...Hallo Andreas,
> Hast du den Infragistcs Form 11.1?
Ja> Ich würde dir das dann auf dropbox legen, so das du das laden kannst.
Poste bitte den Link dazu.Gru�?
Marcel -
Hallo Andreas,
> Bin mal gespannt was du da rausfindest.
Herausgefunden habe ich das, was Elmar bereits vermutet hatte ;-)
AppointmentID ist NULL nach dem ersten Speichern des Datensatzes. Wenn Du nun den Datensatz bearbeitest, ändert sich dessen Status auf DataRowState.Modified. Beim erneuten Speichern versucht der Adapter wg. dem vorhandenen UpdateCommand ("UPDATE Appointments [...] WHERE (AppointmentId = ?)") einen Datensatz mit AppointmentID=NULL zu finden (das steht nämlich unter row[0, DataRowVersion.Original]), was angesichts des zwischenzeitlich autoinkrementierten Feldes natürlich fehlschlägt: AppointmentID hat nun in Access einen inkrementierten Zahlenwert und hat nur auf .NET-Seite noch einen NULL-Wert.
Was tun? - Das, was Elmar schon vorgeschlagen hat, bzw. was in Elmar's Link bezügl. Microsoft Access vorgeschlagen wird:
- Adapter.Update() nur mit den tatsächlichen Änderungen aufrufen
- das RowUpdated-Ereignis abonnieren
- im RowUpdated-Handler, nach dem Insert des neuen Datensatzes, gleich die AppointmentID abfragen und in die Zeile schreiben
- die DataTable mit den tatsächlichen Änderungen mit der Appointments-Tabelle "mergen".Das Ganze hat nur einen Haken: Das Zusammenführen der Tabellen (Änderungstabelle, Termintabelle) würde nicht klappen, und plötzlich stünde der eben über Insert eingefügte Datensatz zweimal in der UI da, einmal mit AppointmentID NULL und einmal mit der tatsächlichen AppointmentID, die Access vergeben hat und die wir im RowUpdated-Handler abgefragt haben.
Warum aber funktioniert DataTable.Merge() nicht? - Weil die Appointments-Tabelle keinen Primärschlüssel hat und keine AutoIncrement-Eigenschaften definiert wurden. Aus der Dokumentation:
Beim Zusammenführen einer neuen Quell-DataTable mit dem Ziel werden Quellzeilen mit dem DataRowState-Wert Unchanged, Modified oder Deleted mit den Zielzeilen zusammengeführt, die dieselben Primärschlüsselwerte enthalten.
Das kann aber nachgeholt werden. Am einfachsten, indem man das Schema manuell abruft (man könnte freilich auch Tabellen-Mappings verwenden und den PrimaryKey manuell definieren):// Infragistics.Win.UltraWinSchedule.Samples.WinScheduleDatabaseSupportBase-Klasse public DataSet DataSet { //[...] dataAdapter = this.DataAdapterForAppointments; dataAdapter.FillSchema(this._dataSet, SchemaType.Source, WinScheduleDatabaseSupportBase.APPOINTMENTS_TABLE_NAME); DataColumn appointmentIdColumn = this.Appointments.Columns[0]; appointmentIdColumn.AutoIncrementSeed = -1; appointmentIdColumn.AutoIncrementStep = -1; dataAdapter.Fill( this._dataSet, WinScheduleDatabaseSupportBase.APPOINTMENTS_TABLE_NAME ); //[...] return this._dataSet; }
Also erst richten wir uns die Tabelle so ein, wie wir sie haben wollen, und erst dann rufen wir die Daten ab. Alles andere ist eine einfache Copy-and-Paste-Aktion aus der MSDN-Dokumentation:
public void UpdateAppointmentsTable() { if ( this.HasAppointmentChanges == false ) return; try { long hierWirdUpgedatet; DataTable appointmentsTable = this.DataSet.Tables[WinScheduleMSSQLServerSupport.APPOINTMENTS_TABLE_NAME]; DataTable appointmentChanges = appointmentsTable.GetChanges(); this.DataAdapterForAppointments.RowUpdated += new OleDbRowUpdatedEventHandler(Adapter_RowUpdated); this.DataAdapterForAppointments.Update(appointmentChanges); appointmentsTable.Merge(appointmentChanges); appointmentsTable.AcceptChanges(); } catch(Exception ee) { MessageBox.Show(string.Format("DB Error = {0}",ee.Message)); } this._hasAppointmentChanges = false; } void Adapter_RowUpdated(object sender, OleDbRowUpdatedEventArgs e) { if (e.StatementType == StatementType.Insert) { OleDbCommand cmdNewID = new OleDbCommand("SELECT @@IDENTITY", this.Connection); e.Row["AppointmentID"] = (int)cmdNewID.ExecuteScalar(); e.Status = UpdateStatus.SkipCurrentRow; } }
Gruß
Marcel- Bearbeitet Marcel RomaModerator Donnerstag, 10. November 2011 10:36 Link hinzugefügt
-
Ha , wie schön das es Leute gibt, die richtig Ahnung haben. (Werd ich ja richtig Neidisch)Vielen Dank Marcel und Danke an Elmar.Gru�?AndreasPS: Jetzt muss ich erstmal Infragistics zusammen scheissen, das die ein Fehlerhaftes Sample ausliefern.......
"Marcel Roma" schrieb im Newsbeitrag news:7560afc3-ae24-4c84-8ae3-16acde9bb452@communitybridge.codeplex.com...Hallo Andreas,
> Bin mal gespannt was du da rausfindest.
Herausgefunden habe ich das, was Elmar bereits vermutet hatte ;-)
AppointmentID ist NULL nach dem ersten Speichern des Datensatzes. Wenn Du nun den Datensatz bearbeitest, ändert sich dessen Status auf DataRowState.Modified. Beim erneuten Speichern versucht der Adapter wg. dem vorhandenen UpdateCommand ("UPDATE Appointments [...] WHERE (AppointmentId = ?)") einen Datensatz mit AppointmentID=NULL zu finden (das steht nämlich unter row[0, DataRowVersion.Original]), was angesichts des zwischenzeitlich autoinkrementierten Feldes natürlich fehlschlägt: AppointmentID hat nun in Access einen inkrementierten Zahlenwert und hat nur auf .NET-Seite noch einen NULL-Wert.
Was tun? - Das, was Elmar schon vorgeschlagen hat, bzw. was in Elmar's Link bezügl. Microsoft Access vorgeschlagen wird:
- Adapter.Update() nur mit den tatsächlichen �?nderungen aufrufen
- das RowUpdated-Ereignis abonnieren
- im RowUpdated-Handler, nach dem Insert des neuen Datensatzes, gleich die AppointmentID abfragen und in die Zeile schreiben
- die DataTable mit den tatsächlichen �?nderungen mit der Appointments-Tabelle "mergen".Das Ganze hat nur einen Haken: Das Zusammenführen der Tabellen (�?nderungstabelle, Termintabelle) würde nicht klappen, und plötzlich stünde der eben über Insert eingefügte Datensatz zweimal in der UI da, einmal mit AppointmentID NULL und einmal mit der tatsächlichen AppointmentID, die Access vergeben hat und die wir im RowUpdated-Handler abgefragt haben.
Warum aber funktioniert DataTable.Merge() nicht? - Weil die Appointments-Tabelle keinen Primärschlüssel hat und keine AutoIncrement-Eigenschaften definiert wurden. Aus der Dokumentation:
Beim Zusammenführen einer neuen Quell-DataTable mit dem Ziel werden Quellzeilen mit dem DataRowState-Wert Unchanged, Modified oder Deleted mit den Zielzeilen zusammengeführt, die dieselben Primärschlüsselwerte enthalten.
Das kann aber nachgeholt werden. Am einfachsten, indem man das Schema manuell abruft (man könnte freilich auch Tabellen-Mappings verwenden und den PrimaryKey manuell definieren):// Infragistics.Win.UltraWinSchedule.Samples.WinScheduleDatabaseSupportBase-Klasse public DataSet DataSet { //[...] dataAdapter = this.DataAdapterForAppointments; dataAdapter.FillSchema(this._dataSet, SchemaType.Source, WinScheduleDatabaseSupportBase.APPOINTMENTS_TABLE_NAME); DataColumn appointmentIdColumn = this.Appointments.Columns[0]; appointmentIdColumn.AutoIncrementSeed = -1; appointmentIdColumn.AutoIncrementStep = -1; dataAdapter.Fill( this._dataSet, WinScheduleDatabaseSupportBase.APPOINTMENTS_TABLE_NAME ); //[...] return this._dataSet; }
Also erst richten wir uns die Tabelle so ein, wie wir sie haben wollen, und erst dann rufen wir die Daten ab. Alles andere ist eine einfache Copy-and-Paste-Aktion aus der MSDN-Dokumentation:
public void UpdateAppointmentsTable() { if ( this.HasAppointmentChanges == false ) return; try { long hierWirdUpgedatet; DataTable appointmentsTable = this.DataSet.Tables[WinScheduleMSSQLServerSupport.APPOINTMENTS_TABLE_NAME]; DataTable appointmentChanges = appointmentsTable.GetChanges(); this.DataAdapterForAppointments.RowUpdated += new OleDbRowUpdatedEventHandler(Adapter_RowUpdated); this.DataAdapterForAppointments.Update(appointmentChanges); appointmentsTable.Merge(appointmentChanges); appointmentsTable.AcceptChanges(); } catch(Exception ee) { MessageBox.Show(string.Format("DB Error = {0}",ee.Message)); } this._hasAppointmentChanges = false; } void Adapter_RowUpdated(object sender, OleDbRowUpdatedEventArgs e) { if (e.StatementType == StatementType.Insert) { OleDbCommand cmdNewID = new OleDbCommand("SELECT @@IDENTITY", this.Connection); e.Row["AppointmentID"] = (int)cmdNewID.ExecuteScalar(); e.Status = UpdateStatus.SkipCurrentRow; } }
Gru�?
Marcel
-
Hallo Andreas Waning,
Ich möchte Dich bitte folgendes lesen und die Beiträge die Dir geholfen haben zu bewerten.
Vielen Dank.
Nutzen Sie die Bewertungsfunktionen ("Antwort" und "Hilfreich") in denMSDN Foren! Unter anderem können andere später eine Lösung schneller finden. Es ist also wünschenswert, dass die fragenden (Benutzer) die Postings/Beiträge anderer Beantworter bewerten.
Hier dazu die wichtigsten Anhaltspunkte aus den Forenregeln und FAQs.
Lösungsbeiträge als „Die Antwort“ markieren
Bitte markieren Sie den Beitrag, der zur Lösung geführt hat, als "Die Antwort". Durch Bewerten eines Beitrags als "Die Antwort" können andere Teilnehmer die Lösung schneller finden. Außerdem können Sie dem Benutzer, der die Antwort eingereicht hat, für seinen Beitrag danken und zur Steigerung der Antwortqualität in der Diskussionsgruppe beitragen.
[Quelle: Forenregeln]
Wie bewerte ich einen Beitrag? Um einen Beitrag als hilfreich zu bewerten, klicken Sie in einem beliebigen Beitrag auf Als hilfreich bewerten. Sie können Ihre Stimme nur einmal für einen Beitrag abgeben.
[Quelle: Häufig gestellte Fragen]Grüße,
Robert
- Bearbeitet Robert BreitenhoferModerator Donnerstag, 10. November 2011 17:05 Formatierung
-
Hallo Robert,1. ich habe meine Bridge Software upgedatet. Woran kannst du sehen, dass ich eine veraltete Version verwendet habe ?2. Für Bewertungen muss ich wahrscheinlich auf die Msdn Seite gehen, oder ?
(Da sollte sich Microsoft was einfallen lassen, dass das alles etwas komfortabler geht. Einloggen, Forum wählen, Beitrag suchen usw...)Diesen Beitrag werde ich in Kürze bewerten.Danke an alle,Andreas"Robert Breitenhofer" schrieb im Newsbeitrag news:c6a043dc-7664-4a43-bb91-210d78f22526@communitybridge.codeplex.com...Hallo Andreas Waning,
Ich möchte Dich bitte folgendes lesen und die Beiträge die Dir geholfen haben zu bewerten.
Vielen Dank.
Nutzen Sie die Bewertungsfunktionen ("Antwort" und "Hilfreich") in denMSDN Foren! Unter anderem können andere später eine Lösung schneller finden. Es ist also wünschenswert, dass die fragenden (Benutzer) die Postings/Beiträge anderer Beantworter bewerten.
Hier dazu die wichtigsten Anhaltspunkte aus den Forenregeln und FAQs.
Lösungsbeiträge als �??Die Antwort�?? markieren
Bitte markieren Sie den Beitrag, der zur Lösung geführt hat, als "Die Antwort". Durch Bewerten eines Beitrags als "Die Antwort" können andere Teilnehmer die Lösung schneller finden. Au�?erdem können Sie dem Benutzer, der die Antwort eingereicht hat, für seinen Beitrag danken und zur Steigerung der Antwortqualität in der Diskussionsgruppe beitragen.
[Quelle: Forenregeln]
Wie bewerte ich einen Beitrag? Um einen Beitrag als hilfreich zu bewerten, klicken Sie in einem beliebigen Beitrag auf Als hilfreich bewerten. Sie können Ihre Stimme nur einmal für einen Beitrag abgeben.
[Quelle: Häufig gestellte Fragen]Grü�?e,
Robert
-
1. ich habe meine Bridge Software upgedatet. Woran kannst du sehen, dass ich eine veraltete Version verwendet habe ?
Hallo Andreas Waning,
Man kann die Version sehen wenn man in einem Beitrag auf Bearbeiten klickt (man muss auf die MSDN Web-Seite gehen) und dann am Ende des Beitrages ein kleines Anchor Zeichen sieht. Wenn man mit der Mouse über dieses Anchor Zeichen geht wird z.B. Microsoft Windows Live Mail 14.0.8089.726 via Community Forums NNTP Server 1.1.44.0 angezeigt…also man sieht den Client und die Version der Community Forums NNTP Bridge.
2. Für Bewertungen muss ich wahrscheinlich auf die Msdn Seite gehen, oder ?
Genau. Man muss auf die MSDN Web-Seite gehen.
Diesen Beitrag werde ich in Kürze bewerten.
Vielen Dank.
Grüße,
Robert
-