Autor |
Beitrag |
Betasteter
      
Beiträge: 19
WinXP
C# (VS 2008)
|
Verfasst: Mo 22.08.11 10:48
Das Projekt bedient eine MS SQL 2005 Datenbank über ADO.NET.
Wenn ich nun testweise während der Arbeit mit dem Programm in der Datenbank einen Wert der gerade in Bearbeitung befindlichen Zeile ändere, tritt beim Speichern mit dem Programm KEINE DBConcurrencyException auf, was nicht gewünscht ist.
Die Update-Funktion:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| internal static void Update(DataRow dataRow) { try { tableAdapter.Update(dataRow); } catch (DBConcurrencyException ex) { ShowConcurrencyMessage(ex); Load(); } } |
"Vollständige Parallelität verwenden" ist aktiviert.
Eigentlich sollte doch standardmäßig immer eine Exception geworfen werden? Kann ich das irgendwo aus Versehen abgestellt haben?
|
|
Betasteter 
      
Beiträge: 19
WinXP
C# (VS 2008)
|
Verfasst: Mo 22.08.11 11:36
Habe das Problem eingrenzen können.
Die Tabelle, die bearbeitet wird, ist einem anderen Schema als dbo zugeordnet.
Wenn ich eine Testtabelle im Schema dbo erstelle und den Updatebefehl auf diese teste, wird seltsamerweise eine Exception geworfen.
Fortsetzung folgt...
|
|
Betasteter 
      
Beiträge: 19
WinXP
C# (VS 2008)
|
Verfasst: Mo 22.08.11 12:38
Finde leider keine Lösung.
Habe folgendes versucht:
- Dem Benutzer, der sich mit der DB verbindet, alle Rechte an der Tabelle zu geben
- Eine Datenbankrolle als Besitzer des Schemas zu definieren und den Benutzer der Rolle zugeordnet
Obwohl mir nichts mehr einfällt, vermute ich dass das Problem mit der Schemadefinition zusammenhängt.
|
|
Betasteter 
      
Beiträge: 19
WinXP
C# (VS 2008)
|
Verfasst: Mi 24.08.11 11:00
Habe das Problem gefunden, es hat doch nichts mit dem Schema zu tun:
Die Tableadapter, die ich verwende, werden erst zur Laufzeit erzeugt. Wenn ich einen Tableadapter verwende, den der Designer erstellt hat, funktioniert die Vollständige Parallelität und es werden DBConcurrencyException geworfen.
Das liegt daran, dass die vom Designer erzeugten Tableadapter im UpdateCommand noch die Select-Abfrage zur Prüfung auf Änderungen vorgeschaltet haben, die zur Laufzeit erzeugten Tableadapter allerdings nicht.
Ich bin auf Lösungssuche.
Edit: Vorerst ist alles zu vergessen, kann das Problem so nicht reproduzieren.
Ich weiß also nichts, es hängt vielleicht dem Schema zusammen, vielleicht auch mit dem TableAdapter, ich suche weiter.
|
|
dark-destination1988
      
Beiträge: 178
Erhaltene Danke: 21
|
Verfasst: Mi 24.08.11 12:32
das nenn ich learning by doing 
|
|
Betasteter 
      
Beiträge: 19
WinXP
C# (VS 2008)
|
Verfasst: Mi 24.08.11 14:28
Problem gelöst.
Wenn in einer beliebigen Tabellenspalte in MS SQL 2005 der Datentyp nvarchar(MAX) verwendet wird, wirft diese Tabelle keine DBConcurrencyExceptions, egal welche Spalte geändert wurde. Warum auch immer.
Wenn ich den Datentyp in z.B. nvarchar(500) ändere, werden DBConcurrencyExceptions geworfen.
Hat jemand vielleicht eine Erklärung dafür?
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 24.08.11 16:16
Die Erklärung dürfte ja wohl sein, dass das ADO.NET-Team an der Stelle keine möglicherweise zu teure Query erzeugen wollte. Ich denke, da hast du einfach die Grenze der beschränkten ADO.NET-Concurrency überschritten. Jedes vernünftige System wie NHibernate führt dafür eine Version-Column in der Tabelle mit, die bei einem Update inkrementiert wird.
_________________ >λ=
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 24.08.11 17:28
Zitat: | Das liegt daran, dass die vom Designer erzeugten Tableadapter im UpdateCommand noch die Select-Abfrage zur Prüfung auf Änderungen vorgeschaltet haben, die zur Laufzeit erzeugten Tableadapter allerdings nicht. |
Sollte nicht einfach in der Where Clause auf die entsprechende Spalte getestet werden? Ich wüsste sonst auch nicht wofür ein Select vor dem Update gut wäre. Insbesondere da sich der Datenbank Inhalt ja zwischen Select und Update wieder geändert haben könnte.
Das update SQL sollte ja in etwa so aussehen
SQL-Anweisung 1:
| Update Table set Spalte1 = neuerWert1, Spalte2 = neuerWert2 Where Spalte1 = alterWerte1 and Spalte2 = alterWert2 |
Wenn die Spalte in der Where Clause bei dir fehlt kannst du das SQL in TableAdapter.UpdateCommand.CommandText einfach nach deinem Gusto anpassen(Ich würde das eh grundsätzlich tun und nicht dem Wizzard überlassen. Ich trau dem nicht).
|
|
Betasteter 
      
Beiträge: 19
WinXP
C# (VS 2008)
|
Verfasst: Do 25.08.11 10:36
Danke für die Hinweise.
@Ralf Jansen: Der Post von mir war zu vorschnell, die Update-Befehle der Tableadapter sehen gleich aus, egal ob vom Designer oder zur Laufzeit erzeugt. Irgendwie hatte ich da was falsches gesehen und direkt Schlüsse gezogen.
Allerdings klingt dein Vorschlag gut, danke.
@Kha: Das klingt auch gut, ist für meine Bedürfnisse aber nicht nötig. Eigentlich hätte es sogar gereicht ohne Concurrency Kontrolle zu arbeiten und einfach den letzten Update zu übernehmen.
|
|