Hab mal ne Frage zum Verständnis.
Ist es möglich eine StoredProcedure im Zusammenhang mit einem DataAdapter.Update(DataSet) aufzurufen???
Wenn ja, wie würde denn sowas aussehen?
Vielen Dank für Eure Informationen
Ben
Ich vermute, nein: Die DbCommand-Klasse unterscheidet für CommandType zwischen StoredProcedure und Text (also "normaler" Befehl).
Aber ich sehe sowieso keinen Sinn darin, einen UPDATE-Befehl aufzurufen, wenn eine StoredProcedure benötigt wird. (Aber selbstverständlich kannst Du über eine SProc Updates ausführen.)
Vielleicht hilft Dir aber auch die CommandBuilder-Klasse besser. Jürgen
hallo BenFire,
ich vermute dass es möglich ist, da du dem DataAdapter die entsprechendne Commands zuweisen musst. Ich bezweifle aber, dass dir das viel bringt, außer relativ unflexiblen Abfrage-Code in den Stored Procedures. Für ein Update genügt doch eine parametrisierte SQL-Query völlig aus. Und wenn du die Command's auch noch mit dem CommandBuilder erstellen lässt, hast du richtig viel Tipparbeit gespart.
-yellow
Selbst ein Weg von tausend Meilen beginnt mit einem Schritt (chinesisches Sprichwort).
Mein Blog: Yellow's Blog auf sqlgut.de
Es ist definitiv möglich!
Und zwar mit Command.UpdateCommand =
SqlCommand UpdateCommand = new SqlCommand();
UpdateCommand.Connection = this.Connection;
etc..
DataAdapter.UpdateCommand = UpdateCommand;
Es mit einem CommandBuilder zu machen ist die zweite Wahl.
Tipparbeit hin oder her.
Jörg
Original von joerg.uth
Es mit einem CommandBuilder zu machen ist die zweite Wahl.
Tipparbeit hin oder her.
Weshalb nicht den CommandBuilder die SQLStatements generieren lassen?
-yellow
Selbst ein Weg von tausend Meilen beginnt mit einem Schritt (chinesisches Sprichwort).
Mein Blog: Yellow's Blog auf sqlgut.de
Original von Yellow
Original von joerg.uth
Es mit einem CommandBuilder zu machen ist die zweite Wahl.
Tipparbeit hin oder her.
Weshalb nicht den CommandBuilder die SQLStatements generieren lassen?-yellow
naja...was will ich denn da mit dem Commandbuilder SQL-Statements erzeugen lassen?
Meine SQL Statements stehen doch in der SP....zumindest hatte ich das vor.
Ich will eigentlich nur der Storedprocedure über Ihre eingangsparameter nach und nach jede Zeile übergeben. (die eingangsparameter sind die Spalten der Tabelle)
soll ich dann für jede Zeile extra ein ExecuteNonQuery Aufrufen?
Ich dacht es ist performanter das ganze per DataAdapter mit einmal rüberzuwurschteln. ???
Der Adapter macht auch nur ExecuteNonQuery, ist also nicht schneller,
als wenn Du es von Hand machst, es ist nur in einer Zeile Passiert.
Und natürlich gehen SP's, aber speziell seit FW 2.0 ist der CommandBuilder
in einigen Situationen besser.
Du kannst z.B. einstellen das er TimeStamp-Columns als Eindeutigkeitsmerkmal
ansieht, oder nur die Spalten überträgt, die sich geändert haben.
Und nur weil ständig irgendwelche DBA's erzählen, das SP's besser sind,
muss das nicht immer der fall sein.
Aber schau Dir mal z.B. http://www.nettiers.com/ an, die generieren SP's
für den Zugriff.
die SP soll ja für ein INSERT sein....nicht für ein reines Update.
Deswegen dürfte mir der Commandbuilder da nicht so viel nutzen.
Da ich ja wie gesagt das Insert der SP überlassen will 😁
Wenn man schon einen SQL-Server verwendet, dann kann und sollte man auch
die gespeicherten Prozeduren verwenden, weil man hiermit einfach die bessere Performance hat.
Nutze die Möglichkeiten 🙂
Jörg
Hallo Ben,
also in Deinem allerersten Beitrag hattest Du nach UPDATE gefragt und nicht nach INSERT... (Das kann zu Missverständnissen führen.) In beiden Fällen kannst Du mit CommandBuilder oder mit eigenen Befehlen arbeiten (anders als ich in meiner ersten Vermutung geäußert hatte).
Der CommandBuilder erzeugt automatisch Befehle; Du ersparst Dir die Schreibarbeit. Eigene Befehle (siehe joerg.uth) machen Dich flexibler.
Zum CommandBuilder zeigt Dir die Doku, wie Du Dir die Arbeit erleichterst:1.Hole die Tabellenstruktur mit einem Select. 1.Lass Dir daraus INSERT und UPDATE erstellen. 1.Speichere die Daten automatisch.
Da ich über DataFactory arbeite, kannst Du meine Befehle nicht 1:1 übernehmen; aber Du kannst Dich daran orientieren, was Du in welcher Reihenfolge benötigst:
DataAdapter1.SelectCommand = dataFactory.CreateCommand();
DataAdapter1.SelectCommand.Connection = conn;
DataAdapter1.SelectCommand.CommandText = "SELECT * FROM Tabelle WHERE 0=1";
// CommandBuilder erzeugen und zuordnen
CommandBuilder1 = dataFactory.CreateCommandBuilder();
CommandBuilder1.DataAdapter = DataAdapter1;
// jetzt Befehle ausführen
DataAdapter1.Fill(Dataset1, tbl.TableName);
conn.Close();
// die erzeugten Commands sollen übernommen werden; das scheint nicht
// automatisch abzulaufen
DataAdapter1.InsertCommand = CommandBuilder1.GetInsertCommand();
DataAdapter1.DeleteCommand = CommandBuilder1.GetDeleteCommand();
DataAdapter1.UpdateCommand = CommandBuilder1.GetUpdateCommand();
// viel, viel später: Änderungen automatisch speichern
DataAdapter1.Update(DataTable1);
Der Befehl ruft automatisch Insert + Update + Delete auf - das ist der große Vorteil von CommandBuilder in Verbindung mit DataAdapter. (Dies funktioniert meistens nur innerhalb einer Tabelle, aber nicht mit ForeignKeys.)
Ich will eigentlich nur der Storedprocedure über Ihre eingangsparameter nach und nach jede Zeile übergeben. (die eingangsparameter sind die Spalten der Tabelle)
soll ich dann für jede Zeile extra ein ExecuteNonQuery Aufrufen?
Wenn Du die Speicherung über eine StoredProcedure vornehmen willst (z.B. wegen eigener Eingabeprüfungen und Verknüpfungen), musst Du die Befehle und vor allem die Parameter selbst direkt zuordnen - siehe die Anleitung von joerg.uth.
Also nochmal: DataAdapter1.Update() ruft automatisch die zugeordneten Insert/Update/DeleteCommands auf. Es kommt "nur" darauf an, wer diese Befehle erzeugt. Jürgen
Ich bezweifle, dass du dadurch Vorteile haben wirst. Ich denke eher du kaufst dir damit Nachteile ein, wie Unflexibilität etc., nennenswerte Geschwindigkeitsvorteile wirst du jedenfalls nicht haben, da beispielsweise der SQL-Server für parametrisierte SQL-Anweisungen ebenfalls einen wiederverwendbaren Ausführungsplan erstellt. Was machst du wenn du mehrere Versionen deiner Anwendung / Komponente parallel fährst, weil du die eine Version weiterentwickelst, die ältere Version nur noch bugfixt etc... meiner Meinung nach gewinnst du damit nur einen höheren Pflegeaufwand. Stored Procedures und Stored Functions in allen Ehren, aber ich meine, man sollte sie nur bei komplexer Logik, die viele Daten handelt und wenig zurück gibt, verwenden.
-yellow
Selbst ein Weg von tausend Meilen beginnt mit einem Schritt (chinesisches Sprichwort).
Mein Blog: Yellow's Blog auf sqlgut.de
Ja sorry das hatte ich vielleicht falsch formuliert.
aber wenn ich mit dem DataAdapter ein Insert ausführen will schreib ich ja trotzdem:
DA.Update(DS,DT);
aber stimmt schon war mein fehler 😉
Original von joerg.uth
Wenn man schon einen SQL-Server verwendet, dann kann und sollte man auch
die gespeicherten Prozeduren verwenden, weil man hiermit einfach die bessere Performance hat.
...und den höheren Pflegeaufwand... in den meisten Anwendungen ist ein Insert, Update und Delete weniger Zeitkritisch, viel mehr sollte man sein Augenmerk auf mögliche Parallelitätsverletzungen werfen...
-yellow
Selbst ein Weg von tausend Meilen beginnt mit einem Schritt (chinesisches Sprichwort).
Mein Blog: Yellow's Blog auf sqlgut.de
Ja sorry das hatte ich vielleicht falsch formuliert.
aber wenn ich mit dem DataAdapter ein Insert ausführen will schreib ich ja trotzdem:
DA.Update(DS,DT);
aber stimmt schon war mein fehler 😉
Original von Yellow
Ich bezweifle, dass du dadurch Vorteile haben wirst. Ich denke eher du kaufst dir damit Nachteile ein, wie Unflexibilität etc., nennenswerte Geschwindigkeitsvorteile wirst du jedenfalls nicht haben, da beispielsweise der SQL-Server für parametrisierte SQL-Anweisungen ebenfalls einen wiederverwendbaren Ausführungsplan erstellt. Was machst du wenn du mehrere Versionen deiner Anwendung / Komponente parallel fährst, weil du die eine Version weiterentwickelst, die ältere Version nur noch bugfixt etc... meiner Meinung nach gewinnst du damit nur einen höheren Pflegeaufwand. Stored Procedures und Stored Functions in allen Ehren, aber ich meine, man sollte sie nur bei komplexer Logik, die viele Daten handelt und wenig zurück gibt, verwenden.-yellow
Der eigentlich Grund, warum ich den ganzen Spass über eine StoredProcedure mache ist, dass ich vorhabe die Tabelle in die das INSERT ausgeführt wird in eine Normalform zu bringen.
Die Procedur soll also dazu dienen den eingegeben Parameter (z.b. ein TRUE für Ergebnis) durch aufruf einer Unterprocedur (welche in der Ergebnisnistabelle dann nach TRUE sucht und die ID zurückgibt) so zu interpretieren, dass nur die ID von TRUE in meine Tabelle geschrieben wird.
Wenn das anders gehen sollte....ich bin für jegliche Tips offen.
Aber nun hab ich halt erstmal den Weg über Stored Procedures eingeschlagen...was anscheinend nicht funktioniert :S X( 🤔
EDIT: Mein Post war zu spät.
Hallo BenFire,
Warum willst Du das INSERT über eine Gespeicherte Prozedur abwickeln? Welche Vorteile soll das haben?
Sag nicht, dass es wesentlich schneller ist. Das stimmt nicht. So simple Befehle wie "INSERT Tabelle (Feld1, Feld2) VALUES (@val1, @val2)" kann der SQL Server wiedererkennen und den gespeicherten Ausführungsplan verwenden. Da die Werte parametrisiert sind, ist das für den SQL kein Problem.
Gespeicherte Prozeduren sind sinnvoll bei komplexen Berechnungen, die große Datenmengen betreffen. Der Geschwindigkeitsvorteil bei einfachen INSERTs, UPDATEs und DELETEs ist Nahe zu bei Null.
Beim Speichern kommt es ohnehin nicht so auf die Geschwindigkeit an, sondern auf Konsistenz. Das wiederum fördert der CommandBuilder, da der Parallelitätsverletzungen bei MultiUser-Zugriff auf die DB automatisch erkennt (Einstellbar über ConflictOption). Lese-Zugriffe müssen schnell sein. Aber auch da, macht es keinen Sinn für Abfragen wie "SELECT * FROM Tabelle WHERE ID=@id" in SPs zu packen.
Ich denke, dass viele Leute Gespeicherte Prozeduren einsetzen, weil es in vielen Büchern über SQL Server steht. Der Haken an der Sache ist, dass Bücher über SQL Server sich nur um den SQL Server drehen.
Original von BenFire
Der eigentlich Grund, warum ich den ganzen Spass über eine StoredProcedure mache ist, dass ich vorhabe die Tabelle in die das INSERT ausgeführt wird in eine Normalform zu bringen.
Die Procedur soll also dazu dienen den eingegeben Parameter (z.b. ein TRUE für Ergebnis) durch aufruf einer Unterprocedur (welche in der Ergebnisnistabelle dann nach TRUE sucht und die ID zurückgibt) so zu interpretieren, dass nur die ID von TRUE in meine Tabelle geschrieben wird.Wenn das anders gehen sollte....ich bin für jegliche Tips offen.
Aber nun hab ich halt erstmal den Weg über Stored Procedures eingeschlagen...was anscheinend nicht funktioniert :S X( 🤔
Um es richtig zu verstehen, du willst eine flachgebügelte Struktur auf dem Client in normalisierten Tabellen auf der DB unterbringen?
-yellow
Selbst ein Weg von tausend Meilen beginnt mit einem Schritt (chinesisches Sprichwort).
Mein Blog: Yellow's Blog auf sqlgut.de
Original von Rainbird
EDIT: Mein Post war zu spät.Hallo BenFire,
Warum willst Du das INSERT über eine Gespeicherte Prozedur abwickeln? Welche Vorteile soll das haben?
Sag nicht, dass es wesentlich schneller ist. Das stimmt nicht. So simple Befehle wie "INSERT Tabelle (Feld1, Feld2) VALUES (@val1, @val2)" kann der SQL Server wiedererkennen und den gespeicherten Ausführungsplan verwenden. Da die Werte parametrisiert sind, ist das für den SQL kein Problem.
Gespeicherte Prozeduren sind sinnvoll bei komplexen Berechnungen, die große Datenmengen betreffen. Der Geschwindigkeitsvorteil bei einfachen INSERTs, UPDATEs und DELETEs ist Nahe zu bei Null.
Beim Speichern kommt es ohnehin nicht so auf die Geschwindigkeit an, sondern auf Konsistenz. Das wiederum fördert der CommandBuilder, da der Parallelitätsverletzungen bei MultiUser-Zugriff auf die DB automatisch erkennt (Einstellbar über ConflictOption). Lese-Zugriffe müssen schnell sein. Aber auch da, macht es keinen Sinn für Abfragen wie "SELECT * FROM Tabelle WHERE ID=@id" in SPs zu packen.
Ich denke, dass viele Leute Gespeicherte Prozeduren einsetzen, weil es in vielen Büchern über SQL Server steht. Der Haken an der Sache ist, dass Bücher über SQL Server sich nur um den SQL Server drehen.
s.o. ich weiss halt nicht wie ich das sonst anders realisieren soll...
Original von Yellow
Um es richtig zu verstehen, du willst eine flachgebügelte Struktur auf dem Client in normalisierten Tabellen auf der DB unterbringen?-yellow
Nein auf dem Client ist die Struktur eben nicht Flachgebügelt....sondern als XML-File mit den Daten (meist als Strings) vorhanden.
Also muss das "Flachbügeln" im Programm passieren...
Kannst Du beschreiben, was Du genau machen willst (Wie heißen Datei Tabellen, wie sind sie verknüpft und was übergibt der Client)?
Das ist sonst etwas schwer zu durchblicken.
Also passt auf...
eigentlich sollte es ja keine Grundsatzdiskussion zum Sinn/Unsinn bzw. Vor-/Nachteil von Stored Procedures werden.
Meine Ausgangssituatuion ist folgende:
ich habe 2 Tabellen, die rein funktionell gesehn alles erfüllen, was ich brauche (GeraetTabelle, TestsequenzTabelle).
Zu jedem Gerät in der Geraet Tabelle gibt es mehrere Test in der Testtabelle.
Da sich aber nun die Tests für jedes Gerät wiederholen, hatte ich gedacht die Testname,Testergebnisse auszugliedern in seperate Tabellen und in die TestsequenzTabelle nur die jeweilige ID dafür zu schreiben.
Problem an der Sach ist, dass sich die Daten, die in die TestsequenzTabelle geschrieben werden sollen in einem XML-File Vorhanden sind.
Dieses XML File lese ich dann auf ein DataSet ein.
Nun stehen in der DataTable des DataSet ja aber die Kompletten Strings
die ja vorher noch umgewandelt werden müssen, bevor der Insert in die TestsequenzTabelle erfolgen kann.
Ich hatte mir da jetzt gedacht einer StoredProcedure die Parameter (Testname, Messwert, Ergebnis) zu übergeben, und in dieser werden dann wieder "Unterproceduren" aufgerufen, die in den jeweiligen Tabellen die zugehörigen ID suchen und diese gleich in den INSERT-Befehl der Übergeordneten SP einfügen.
So war mein Plan....ich weiss ja nicht, ob das auch noch anders gehen würde. Fakt ist das die Daten im DataSet noch in Stringform vorhanden sind und ich diese halt in ID´s umwandeln müsste.
Vielen Dank für eure Antworten 😁
Hallo Ben,
also wenn ich Deine Beiträge richtig verstanden habe, handelt es sich immer um INSERTs, und die Arbeitsweise in der StoredProcedure ist Dir klar. Dann mach doch das, was joerg.uth vorgeschlagen hat:1.Lies die Xml-Daten in ein passendes Dataset ein, das sich auf string-Felder bezieht.
1.Erzeuge einen SqlCommand als Aufruf der StoredProcedure.
1.Füge die Parameterliste hinzu.
1.Verweise bei den Parametern auf die Felder Deiner Xml-Daten.
1.Ordne diesen SqlCommand dem DataAdapter.InsertCommand zu.
Durch DataAdapter.Update() müssten alle Daten (als Strings) an die SProc übergeben werden; und diese sucht sich selbst die passenden IDs.
Gruß Jürgen
Boaah ich glaub mir is grad aufgefallen, wo mein Fehler liegt.
bei DA.Update hab ich ihm nur das DataSet gegeben und mich geärgert, darüber, dass er noch eine Tabelle haben will, weil ich dachte das ist die Tabelle in die das Insert ausgeführt werden soll.
Nun seh ich aber gerade das da SrcTable steht :S
Ich depp!!!
Werd das morgen gleich mal probieren...heute hab ich keinen Nerv mehr dafür....vielen Dank für eure Geduld.
Mfg
Ben
Original von juetho
Hallo Ben,
also wenn ich Deine Beiträge richtig verstanden habe, handelt es sich immer um INSERTs, und die Arbeitsweise in der StoredProcedure ist Dir klar. Dann mach doch das, was joerg.uth vorgeschlagen hat:1.Lies die Xml-Daten in ein passendes Dataset ein, das sich auf string-Felder bezieht. 1.Erzeuge einen SqlCommand als Aufruf der StoredProcedure. 1.Füge die Parameterliste hinzu. 1.Verweise bei den Parametern auf die Felder Deiner Xml-Daten. 1.Ordne diesen SqlCommand dem DataAdapter.InsertCommand zu.
Durch DataAdapter.Update() müssten alle Daten (als Strings) an die SProc übergeben werden; und diese sucht sich selbst die passenden IDs.
Gruß Jürgen
Ich denke auch, dass es so funktionieren sollte. In deinem Anwendungsfall halte ich es auch für vertretbar eine Stored Procedure zu verwenden. Die Alternative würde hier ebenfalls eher aufwendig sein. Du müsstest die entsprechenden Tabellen aus der Datenbank abrufen, dir im Hauptspeicher eine deiner Zieltabelle entsprechenden DataTable generieren und diese dann über die generierten Commands auf die Datenbank schreiben. Von daher gibt sich der Pflegeaufwand nicht wirklich etwas. Entschuldige wenn wir in deinem Thread eine Diskussion über Sinn und Unsinn von Stored Procedures losgetreten haben, aber es war zu Beginn nicht ganz klar (zumindest mir nicht ersichtlich) worum es dir denn geht.
-yellow
Selbst ein Weg von tausend Meilen beginnt mit einem Schritt (chinesisches Sprichwort).
Mein Blog: Yellow's Blog auf sqlgut.de
So die Sache läuft jetzt...so wie geplant.
Es funktioniert also wirklich so, wie ihr das gesagt hattet.
Ich hätte halt nur schonmal früher den Tabellennamen aus dem DataSet mitgeben sollen 😁
Vielen Dank an euch alle....und seit euch sicher...die nächste Frage wird kommen das ist gewiss 😁