Laden...

Stilfrage: Stored Procedures

Erstellt von OpusDei vor 16 Jahren Letzter Beitrag vor 16 Jahren 2.749 Views
OpusDei Themenstarter:in
98 Beiträge seit 2007
vor 16 Jahren
Stilfrage: Stored Procedures

verwendetes Datenbanksystem: <SqlServer>

So ich mal wieder 😉

Ich bau zur Zeit an einem DatenBank Client der im Grunde selber Tabellen im SqlServer verwalten soll. Also keine Szenario der Form: Man designe sich einmal eine Tabellen und arbeite dann damit. Daher übrigens auch meien ganzen Fragen, wie man Tabellenschemata und Constraints aus der DB ausliest.

Zurück zur App: Ich habe also die komplette Sql DDL nochmal in Klassen gepackt. Es gibt also ne Methode

public void TableCreate(string Name)
        {
            SqlDataAdapter da = new DataCtrl().GetDataAdapter("CREATE TABLE [dbo].[" + Name + "] ( [" + Name + "ID] int IDENTITY (1,1) NOT NULL, CONSTRAINT [PK_" + Name + "] PRIMARY KEY CLUSTERED ( " + Name + "ID ));", DB);
            da.Fill(new DataSet());
            da.Dispose();
        }

und irgendwo steht dann da auch direkt SqlSyntax drin (CREAT TABLE ...). Ich hab überlegt ob das wirklich gut ist. Hab mir paar WebCasts angeguckt und da wird immer von Stored Procedures gesprochen. SQL Syntax direkt im Quellcode scheint eher schlechter Stil zu sein.

Was meint Ihr dazu? Gilt das auch für DDL wenn man weder Tabelle noch DataBase kennt auf der gearbeitet wir. Im Grunde kann ich ja gar keine SP anlegen, da die ja DataBase bezogen sind (AdventureWorks.Programmability.Stored Procedures) , oder gibt es auch nen Ort wo man SP speicher kann, damit alle DB auf der SqlServerInstanz sie nutzen können?

3.825 Beiträge seit 2006
vor 16 Jahren

SQL Syntax direkt im Quellcode scheint eher schlechter Stil zu sein.

Mir ist das egal.

Ich programmiere so dass die Software auf möglichst vielen DB-Servern läuft und da ist es am einfachsten den SQL-Code im Source zu hinterlegen und dann durch Filter jeweils an die DB-Server anzupassen.
Ich habe sogar die gesamte Datenbankstruktur im Source Code enthalten, so dass ich bei Programmstart prüfen kann ob die Datenbankstruktur aktuell ist.

Also ich bin für SQL-Kommandos im Source-Code. 👍

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

OpusDei Themenstarter:in
98 Beiträge seit 2007
vor 16 Jahren

😁 gut, haben wir schonmal eine Meinung, die es mir mit gutem Gewissen erlaubt weiter zu machen wie bisher. Obwohl, eine weitere Stilfrage wirft sich auf, die ich mir aber fast schon selbst beantworten kann: Den Sql Befehl wie im Beispiel als String abzulegen und dann den Parameter anzuhängen ist aber wirklich Murks, oder?

string SqlBefehl = "SELECT * FROM " + Table;

Stichwort Sql-Injection. Alternative: SqlCommand mit SqlParameter, korrekt? Hintergrund: Ich wollt erstmal alles zum laufen bringen, daher der "pragmatische Ansatz" 😉 Würd aber schon gerne vorab klären, wie man eine Datenbankanwendung letztendlich halbwegs professionell aufbaut.

4.207 Beiträge seit 2003
vor 16 Jahren

SQL im Quellcode ist IMHO - sorry - Müll.

So was gehört in eine externe Konfiguration, die man auch nach der Compilezeit noch anpassen kann.

Sonst passieren so Sachen wie, dass man irgendeine exotische Funktion der DB nutzt, diese in einem SP dann geändert wird, juhuu, und dann darf man Code ändern, neu kompilieren, neu testen, neu deployen, ...

Hat man das SQL statt dessen extern, so deployed man nur eine neue XML und das war's.

Außerdem neigt man bei SQL im Code dazu, SQL redundant vorzuhalten. Externalisiert man das, macht man sich mehr Gedanken darüber, die Datenbankzugriffe zu zentralisieren.

Ganz abgesehen davon sind Stored Procedures schlichtweg schneller als im Code abgelegte SQL-Kommandos.

Zu der Frage mit den Parametern: Ja, die Parameter einfahc per + anzuhängen, ist unsicher und öffnet SQL Injection Tür und Tor.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

OpusDei Themenstarter:in
98 Beiträge seit 2007
vor 16 Jahren

Kann man denn SPs so ablegen, dass Sie für jede Datenbank auf dem SqlServer angewendet werden können?

S
489 Beiträge seit 2007
vor 16 Jahren

du kannst versuchen deine SP in die systemdatenbanken zu integrieren - wenn das geht habe es noch nie probiert - dann wäre es möglich, dass sie in jeder Datenbank vorhanden ist.

1.564 Beiträge seit 2007
vor 16 Jahren

Und noch mein Senf...

Ich schließe mich in erster Instanz der Aussage von Golo an. Reine SQL Statements haben im Source eigentlich nix zu suchen.

Zu der Frage von OpusDei jedoch:
Da es sich bei dem von dir geposteten Snippet jedoch um DDL und nicht um DML handelt würde ich wiederum sagen, dass hier das Zusammenbauen von dynamischen Statements um die Datenbank zu erstellen (nicht um sie abzufragen) doch eher im Source aufgehoben sein sollte. Dynamische SQL Statements für DDL kann man auch in einer Prozedur nur als Strings zusammenbauen.

Wenn du nur SQL Server verwendest solltest du dich vielleicht aber eher mal mit SMO beschäftigen. Da hast du eine komplette Library quasi geschenkt und kannst über Source-Code die Datenbank maintainen. Aller:

Table tbl = new Table();
tbl.Columns.Add(...

Grüße
Flo

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

4.207 Beiträge seit 2003
vor 16 Jahren

Auch in diesem Fall würde ich das ganze als .sql-Skript extern halten, und in die Anwendung einlesen ...

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

OpusDei Themenstarter:in
98 Beiträge seit 2007
vor 16 Jahren
3.728 Beiträge seit 2005
vor 16 Jahren
Doch kein Müll

Original von Golo
Sonst passieren so Sachen wie, dass man irgendeine exotische Funktion der DB nutzt, diese in einem SP dann geändert wird, juhuu, und dann darf man Code ändern, neu kompilieren, neu testen, neu deployen, ...

Ob ich eine neue DLL bereitstelle, oder einer neue Konfigurationsdatei ist egal. Auch wenn die SQL-Anweisungen in einer Konfigurationsdatei stehen, muss man neu testen. Deployen muss man sowieso und in den meisten Fällen auch neu kompilieren. Wenn das Resultset z.B. plötzlich ein Feld mehr enthält, muss auch der Code angefasst werden. Und zwar alle Schichten (wenn man denn sein Projekt in Schichten entworfen hat).

Letztendlich vergrößert sich durch ausgelagerte SQL-Anweisungen nur der Entwicklungsaufwand und die Komplexität der Anwendung. Außerdem soll vielleicht nur jeder neugierige Admin, der Zugriff auf die Konfigurationdatei hat, die SQL-Anweisungen sehen oder gar verändern können.

Ich dachte auch mal, dass ausgelagerte SQL-Anweisungen toll wären, hab das aber sehr schnell wieder verforfen. Die angeführten Vorteile existieren in Wirklichkeit gar nicht. Ich schreibe meine SQL-Anweisungen immer direkt in den Code meiner Geschäftskomponenten. Vorteil: Ich weiss immer wo mein Code (das schließt auch SQL-Code mit ein) steht und wo ich anpacken muss, wenn was geändert werden muss. Auch wenn ein neuer Kollege im Team was an meinem Code machen muss, wird er sich schnell zurechtfinden und kann die Änderung bereits nach kurzer Einarbeitungszeit durchführen.

P.S. Wenn ich mich für ein RDBMS entscheide, möchte ich auch dessen vielleicht "exotische" Funktionen verwenden, um die maximale Leistung rauszuholen. Wenn man nie konkret wird, sondern alles immer nur abstrakt halten will, bleibt die Problemlösung meistens auf der Strecke.

M
303 Beiträge seit 2006
vor 16 Jahren

Ich denke auch, dass man es mit der Abstraktion durchaus übertreiben kann. Ich wähle ein bestimmtes Datenbanksystem aus, und will auch dessen Vorteile nutzen.

Ich nutze auch SQL Statements im Code, trenne aber Datenzugriff durch eigene Assemblies von der Anwendung ab. Wenn SQL ausgelagert werden soll, dann in Stored Procedures.

3.728 Beiträge seit 2005
vor 16 Jahren
Gespeicherte Prozeduren

Wobei ich Gespeicherte Prozeduren nur für komplexe Aufgaben einsetze (z.B. immer dann, wenn man nicht ohne temporäre Tabellen auskommt). Gespeicherte Prozeduren mit SQL-Code wie "SELECT * FROM Users WHERE UserName=@name", halte ich für Unfug.

W
32 Beiträge seit 2007
vor 16 Jahren

also, ich überlasse größere Aufgaben der Client Sofware meines Systems lieber dem Server, kleinere Querys hab ich in einer SQlite DB am Client gespeichert.
Der Datentransfer zwischen den verschiedenen Datenbanken und Servern erfolgt via. Stored Procedures, *.csv Files.
Läuft eigentlich relativ Sauber, von SQL im Code würd ich aber eher abraten, sieh erstens hässlich aus, bzw. die Überschaubarkeit leided gewaltig darunter, dh. die Software stirbt mit dir.

"Arbeit ist die altmodische Form der Vermögensbildung in Arbeitnehmerhand."

Wolfram Weidner (*1925), dt. Journalist

3.728 Beiträge seit 2005
vor 16 Jahren
Gespeicherte Prozeduren

@WSX: Versionierst Du Deine Gespeicherten Prozeduren auch in einer Quellcodeverwaltung (SourceSafe, Subversion,CVS, etc ...)?
Wie groß ist das Entwickler-Team?
Auf wie viele Datenbanken sind Deine Gespeicherten Prozeduren verteilt?

Ich stelle diese Fragen, da es nach meiner Erfahrung mit zunehmender Größe des Entwicklungsteams und des Projekts immer schwieriger wird, mit Gespeicherten Prozeduren zu arbeiten. Versionierung, Debugging und gemeinsames Arbeiten ist bei Gespeicherten Prozeduren wesentlich aufwändiger, als z.B. bei C#-Code. Hinzu kommt dass der SQL-Code in Gespeicherten Prozeduren auch nicht schöner ist, als SQL-Anweisungen innerhalb von C#-Klassen.
Es ist vielmehr so, dass große Gespeicherte Prozeduren (Und die werden zwangsläufig groß, da man bei SQL längst nicht die Möglichkeiten zu Strukturierung hat, wie z.B. bei C#) schnell unübersichtlich werden und sich meist kein Anderer, als der Ersteller selbst, trauen diese Konstrukte anzufassen. Frei nach dem Motto: "Fummel bloß nicht dran rum!".

Ich will Gespeicherte prozeduren nicht verteufeln, aber ich denke, dass man sehr sparsam damit umgehen sollte.

J
1.114 Beiträge seit 2007
vor 16 Jahren

Ich schliesse mich Rainbird an. Ich nutze auch in meinen Quellcodes "Select" Statements. Allerdings versuche ich die klein zu halten, d.h. grössere Abfrage über joins und co. versuche ich dann in Views zu kapseln. Nur wenns noch komplizierter wird, lege ich das auch mal in einer Stored Procedure ab.

Vermeiden sollte man auf jedenfall "Select *" in Anwendungen, sondern immer lieber alle nötigen Spalten explizit angeben. Das vermeidet böse Überraschungen, wenn mal eine Tabellenspaöte hinzukommt, die aber beispielsweise nicht in jeder Abfrage benötigt.

S
8.746 Beiträge seit 2005
vor 16 Jahren

Bin da ganz bei Rainbird. Sehe die gleichen Problem wie er und habe die gleichen Erfahrungen gemacht. Meines Erachtens sind Stored Procs eher Alt-Lasten oder im Altlastenumfeld einzusetzen.

OpusDei Themenstarter:in
98 Beiträge seit 2007
vor 16 Jahren

Gibt es eine Möglichkeit parametrisiert auf Tabellen zuzugreifen, deren Namen man bei Entwurfszeit noch nicht kennt? Ich nutze zZ

string sql = "Select * from " + TableName;

aber das ist ja nicht der Weisheit letzter Schluss. SqlParameter will aber nicht so wie ich will. Siehe auch: -->