[ACCESS 03] Schreiboperation (Update, Insert, Delete) auf ein Query (bzw. View) mittels OleDbDataAdapter
-
14 Agustus 2012 16:26
Hallo Freunde,
ich habe zwei Quelltabellen, die in einem Access-Query (...die Access Bezeichnung für View) joine. Auf dieses Query greife ich in meiner C#.NET-Applikation mittels OleDbDataAdapter zu und fülle mein DataSet. Nun möchte ich Zeilen verändern, hinzufügen und löschen.
PROBLEM:
Die OleDbCommandBuilder ist lt. Exception zu blöd, bei mehreren Quelltabellen, entsprechende SQL-Statements zu generieren.
Ein erster "händischer" Versuch, Daten per OleDbCommand("INSERT INTO myQuery VALUES (1, 2, 3)", myCon); in die Query (hab die Query wie eine normale Tabelle adressiert) hineinzuschreiben gelingt.
FRAGE:
Wie aber geht es mit einem OleDbDataAdapter? Notfalls müsste ich zeilenweise Updaten und mit Parametern arbeiten, wobei mir kein Weg bekannt ist, die SQL-Statements des DataAdapters direkt zu manipulieren.
MfG
Flux1989
Semua Balasan
-
15 Agustus 2012 4:07
Flux1989 wrote:
Wie aber geht es mit einem OleDbDataAdapter? Notfalls müsste ich
zeilenweise Updaten und mit Parametern arbeiten, wobei mir kein Weg
bekannt ist, die SQL-Statements des DataAdapters direkt zu manipulieren.Wieso öffnest Du nicht einfach eine Connection und dort ein SqlCommand? Dort kannst Du dann den CommandText beliebig setzen und dann ein ExecuteNonQuery ausführen.
Gruss
Henry -
15 Agustus 2012 7:11
Weil ich dann für jede View-Zeile das SQL-Statement manuell setzen müsste,
im Vergleich dazu wäre ein DataTable mit CommandBuilder und da.Update(dt)
um einiges komfortabler.
Alternativ hab ich mir gedacht direkt auf den Quelltabellen zu arbeiten u
d um den entsprechenden Code-Block "Transaktionsfunktionen" zu legen zur
Wahrung der Datenkonsistenz. Hab bisher nur von diesem Konzept gehört,
hat vll jemand ein entsprechendes Code-Snippet parat?
MfG
- Diedit oleh Flux1989 15 Agustus 2012 7:13
-
15 Agustus 2012 10:16
Wieso musst Du da für jede View Zeile das SQL Statement manuell absetzen? mit dem ExecuteNonQuery lassen sich sehr wohl Bulk Updates auf alle Zeilen, welche der Where Bedingung entsprechen, absetzen.
Ich würde nicht mit den Table Adaptors arbeiten, das ist kompilzierter und wird wohl kaum irgendwelche Vorteile bringen.
Gruss
Henry
-
15 Agustus 2012 12:31
mit dem ExecuteNonQuery lassen sich sehr wohl Bulk Updates auf alle Zeilen, welche der Where Bedingung entsprechen, absetzen.
OK, angenommen ich hab ne Tabelle T, mit den Spalten id (autoincrement) und v1 (text) und v2 (text), wobei v2 erstmal nur NULLs enthält:
1 a
2 b
3 c
Angenommen der Algorithmus für v2 lautet:
if(v1 < "m")
return (v2 = "m")
else
return (v2 = v1);
Wenn ich nun die Werte für v2 in jeder Zeile einzeln anhand eines (für alle Zeilen einheitlichen) Algorithmus bestimmen will, wie muss ich dann das SQL-Statement formulieren? v2_var berechne ich momentan in jedem Zeilendurchlauf meines DataReaders:
//Verbindung aufgebaut und Daten aus View in DataReader geladen while(dr.Read()) { v2_var = (dr["v1"] < "m" ? "m" : dr["v1"]) string cmdStr = "UPDATE T SET v2 = " + v2_var + " WHERE id = " + dr["id"]; cmd.CommandText = cmdStr; cmd.ExecuteNonQuery(); }Ein BulkUpdate setzt voraus, dass die upzudatenden Werte vorher bekannt sein müssen..
- Diedit oleh Flux1989 15 Agustus 2012 12:34
-
17 Agustus 2012 6:47
Ich verstehe nicht, wieso Du dazu einen DataReader brauchst. Du willst in der Tabelle T die Spalte v2 abhängig vom Inhalt in v1 ändern. Mit deinem Beispiel wären das 2 Bulk UPDATE Statement, die Du nacheinander abschicken kannst.
Ich gehe davon aus, dass cmd.Connection gesetzt ist. Vergiss' mal alles mit dem Datareader und versuche Folgendes:
cmd.CommandText = "UPDATE T SET v2 = 'm' WHERE v1 < 'm'"; cmd.ExecuteNonQuery(); cmd.CommandText = "UPDATE T SET v2 = v1 WHERE v1 >= 'm'"; cmd.ExecuteNonQuery();
Allenfalls kapselst Du das ganze noch in eine Transaktion und nun sollte die Tabelle T die gewünschten Werte beinhalten. Nun kannst Du, falls Du noch einen Datareader benötigst, diesen öffnen und einlesen.
Gruss
Henry
- Diedit oleh Henry Habermacher 17 Agustus 2012 6:48
-
29 Agustus 2012 15:34
Ich Stimme Henry zu,
Hier ein Beispiel:
public void DatenAktualisieren() { // Aktualisiert Daten in der Datenbank // Variablen deklarieren string constr; // Beinhaltet den Connectionstring zur Datenbank OleDBConnection conn; // Ist die Datenleitung zur Datenbank string strsql; // Beinhaltet den Befehl an die Datenbank // Verbindung zur Datenbank festlegen // Variert leicht, je nachdem welcher Datenbanktyp // Weitere Hilfe unter www.connectionstrings.com constr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\myFolder\\myAccess2007file.accdb;Persist Security Inf" + "o=False;"; conn = new SqlConnection(constr); // Datenleitung wird geöffnet conn.Open(); // Datenbankbefehl wird definiert strsql = "UPDATE Bespieltabelle SET Anrede = 'Frau', Nachname = 'Mustermann' WHERE Kundennummer=4711;" SqlCommand cmd = new SqlCommand(strsql, conn); // Befehlsobjekt ausführen cmd.ExecuteNonQuery(); // Verbindung zur Datenbank schliessen conn.Close(); }Gruß
Michael
-
07 September 2012 14:01
Das Problem ist leider noch nicht gelöst. Habs bisher mit nem Datareader gemacht und für jede gelesene Zeile ein cmd.ExecuteNonQuery gemacht - mit katastrophaler performance.
Die Situation:
Ein DataTable gefüllt mit Daten aus einem View, auf jede Zeile des DataTables wurde ein Algorithmus angewendet.
Nun möchte ich die veränderten Felder zurückschreiben (Update). Bekanntlich ist der OleDbCommandBuilder nicht dazu in der Lage bei mehreren Quelltabellen.
Die Situation vereinfacht sich insofern, als dass nur Daten EINER Quelltabelle geändert und somit zurückgeschrieben werden müssen.
Wie gehe ich da am besten vor? Habe Schwierigkeiten das (Bulk-) Update-Kommando zu formulieren.
Update Quelltabelle SET {alle veränderten Spalten} WHERE {der PK von Quelltabelle ist eine Spalte im DataTable}Gruß
Flux89
- Diedit oleh Flux1989 07 September 2012 14:02
-
07 September 2012 14:52
Verzichte einfach auf den Data Reader, der hat bei einem SQLCommand wenig bis gar nichts nichts zu suchen. Die Primärschlüssel, die Du in den Data Reader eingelesen hast müssen ja bestimmten Kriterien entsprechen, also z.B.
SELECT DeinPK FROM DeineTabelle WHERE irgendwas = irgendwasAnderes
Beschreibe besser, was Du in den Data Reader eingelesen hast. Es gibt mit grosser Wahrscheinlichkeit einen Bulk Update, der das SQL Statemet, mit dem Du den Datareader einliest, integriert.
Im obigen Fall wäre das Statement dann
UPDATE DeineTabelle SET DeinFeld = wasAuchImmer WHERE DeinPK IN ( SELECT DeinPK FROM DeineTabelle WHERE irgendwas = irgendwasAnderes)
Weise dann das SQL Statement dem SQLCommand.CommandText zu und führe ExecuteNonQuery aus.
Gruss
Henry
-
07 September 2012 18:04
Hi Henry,
ich versuche das Szenario noch etwas genauer zu beschreiben:
Die View kombiniert zwei Tabellen T1 und T1, welche eine 1 : 1 Beziehung haben, d.h. jeder PK von T1 kommt maximal in einer Zeile vor. Nun betrachte ich jede Zeile des View und veraendere Felder in T1 anhand von Feleder in T2.
Schliesslich moechte ich T1 updaten (pro View-Zeile sind es mehrere Felder, die in T1 geschrieben werden sollen).
Bin mir zwar nicht sicher, ob es ein Bulk-Update-Kommand gibt, aber ich versuch mich mal:
UPDATE T1 SET c1 = ds.Tables["T1joinT2"].Columns["col1"], c2 = ds.Tables["T1joinT2"].Columns["col1"] WHERE T1.id IN ds.Tables["T1joinT2"].Columns["Tid"]
Sehe ehrlich gesagt nicht, wie ich DataTable und SQL-Updatestatement zusammenbringen kann ??
Danke
Flux89
- Diedit oleh Flux1989 07 September 2012 18:07
-
10 September 2012 2:47
Hallo Flux98
Wir kommen so nicht weiter. Sorry. Solange Du an der DataTable Variable festhälst und nicht verraten willst, was da drin ist, werden wir keine Lösung finden. Du musst, wenn Du einen Bulk Update machen willst, auf diese Variable verzichten. Es muss alles aus der Datenbank kommen, in der Du die Daten ändern willst, weil der Bulk Update ja nicht auf Deine lokalen Programm Variablen zugreifen kann.
Schreibe zuerst mal eine Query, welche das Wunsch-Ergebnis in Feldern ausgibt, indem es diese aus den Werten in T2 ermittelt. In der Where Bedingung musst Du hier dann eben wie in meinem obigen Beispiel das SELECT Statement drin haben, mit dem Du den DataTable füllst, nicht den Data Table selber.
Wenn Du soweit bist, dann änderst Du die Abfrage in einen Update (über den Wizzard) und wählst als zu ändernde Tabelle die Tabelle T1 aus. Dann musst Du noch ausfüllen, in welche Felder die Wunsch Ergebnisse in T1 weggeschrieben werden sollen und nun ist der Bulk Update fertig.
Gruss
Henry
-
13 September 2012 17:30
Hi Henry, ich habs letztendlich so gemacht:
Per Datareader die Query lesen, dabei pro zeile ein DataTable mit den Ergebnisspalten beschreiben und dieses Datatable am schluss updaten. Die Performance-Steigerung liegt im 1000er-Bereich.
Trotzdem vielen dank für deine Mühe. Leider konnte ich deinem letzten Post inhaltlich nicht folgen, iwie versteh ichs net richtig, schätze ich müsste die lösung einmal gesehen habe, bevor ichs selber machen könnte...
Gruß
Flux89
- Diedit oleh Flux1989 13 September 2012 17:31