Laden...

StoredProcedure im Zusammenhang mit DataAdapter.Update

Erstellt von BenFire vor 17 Jahren Letzter Beitrag vor 17 Jahren 3.449 Views
B
BenFire Themenstarter:in
50 Beiträge seit 2006
vor 17 Jahren
StoredProcedure im Zusammenhang mit DataAdapter.Update

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

J
3.331 Beiträge seit 2006
vor 17 Jahren

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

476 Beiträge seit 2004
vor 17 Jahren

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

484 Beiträge seit 2006
vor 17 Jahren

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

476 Beiträge seit 2004
vor 17 Jahren

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

B
BenFire Themenstarter:in
50 Beiträge seit 2006
vor 17 Jahren

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. ???

F
10.010 Beiträge seit 2004
vor 17 Jahren

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.

B
BenFire Themenstarter:in
50 Beiträge seit 2006
vor 17 Jahren

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 😁

484 Beiträge seit 2006
vor 17 Jahren

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

J
3.331 Beiträge seit 2006
vor 17 Jahren

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

476 Beiträge seit 2004
vor 17 Jahren

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

B
BenFire Themenstarter:in
50 Beiträge seit 2006
vor 17 Jahren

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 😉

476 Beiträge seit 2004
vor 17 Jahren

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

B
BenFire Themenstarter:in
50 Beiträge seit 2006
vor 17 Jahren

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( 🤔

3.728 Beiträge seit 2005
vor 17 Jahren
SPs bringen da nix

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.

476 Beiträge seit 2004
vor 17 Jahren

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

B
BenFire Themenstarter:in
50 Beiträge seit 2006
vor 17 Jahren

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...

B
BenFire Themenstarter:in
50 Beiträge seit 2006
vor 17 Jahren

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...

3.728 Beiträge seit 2005
vor 17 Jahren
Infos

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.

B
BenFire Themenstarter:in
50 Beiträge seit 2006
vor 17 Jahren

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 😁

J
3.331 Beiträge seit 2006
vor 17 Jahren

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

B
BenFire Themenstarter:in
50 Beiträge seit 2006
vor 17 Jahren

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

476 Beiträge seit 2004
vor 17 Jahren

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

B
BenFire Themenstarter:in
50 Beiträge seit 2006
vor 17 Jahren

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 😁