Laden...

SQL String Handling

Erstellt von Kriz vor 2 Jahren Letzter Beitrag vor 2 Jahren 624 Views
K
Kriz Themenstarter:in
141 Beiträge seit 2017
vor 2 Jahren
SQL String Handling

Verwendetes Datenbanksystem: SQL

Moin zusammen,

ich hab eine API, die auf eine SQL Datenbank zugreift. Insgesamt sind es grob 300 verschiedenste Abfragen.
Lange Abfragen, die im Code schwer zu lesen sind, habe ich als StoredProcedur angelegt, kürzere Abfragen direkt im Code.
Beim Refactoring ist mir dieses Durcheinander aufgefallen un dich überlege, ob es nicht bessere Lösungen gibt?!
Beispielsweise könnte man ja die Strings auch in eine separate TXT ablegen und abrufen, oder eine statische Klasse nutzen...

Wie handhabt ihr Eure SQL Queries?

463 Beiträge seit 2009
vor 2 Jahren

Also ich habe dazu eine eigene Klasse - im Code ist nur der Befehl zum Nachladen der Befehle fest hinterlegt. Alle anderen Befehle liegen in der Datenbank und werden entweder beim Start oder bei Bedarf nachgeladen.

C
55 Beiträge seit 2020
vor 2 Jahren

Guten Morgen,

Also ich habe auch schon oft darüber nachgedacht wie ich das bei meinen Service machen sollte. Die Idee die Sql Queries in einer txt/sql/json Datei zu hinterlegen hatte ich auch schon. Bin aber letztlich zu dem Schluss gekommen, dass das keine gute Idee ist und zwar aus dem ganz einfachen Grund, das jemand die Datei manipulieren könnte. Die Queries in der Datenbank zu speichern halte aus den selben Grund auch für eine schlechte Idee.

Von Dapper gibt es Beispielsweise einen SQL Builder -> https://www.nuget.org/packages/Dapper.SqlBuilder/
Oder du nutzt wieder ganz klassisch das Entity Framework.

Es gibt sicherlich noch mehr Möglichkeiten das Problem anzugehen.

Grüße

2.094 Beiträge seit 2012
vor 2 Jahren

Warum nicht als embedded resource?

Oder ein Repository, dessen Implementierung größtenteils aus SQL besteht.
Das Ausführen und Mappen übernimmt z.B. Dapper.

Oder direkt ein vollwertiges ORM wie EFCore, dann spart man sich die ganzen SQL Queries.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

3.825 Beiträge seit 2006
vor 2 Jahren

Das wollte ich auch schreiben.

Ich schreibe keinen SQL Code mehr, sondern lasse das vom ORM machen. So ist alles aufgeräumt, typsicher und selbstdokumentierend.

Weiterentwicklung und Fehlersuche ist auch viel einfacher.



Alt : if (such_ar_bez1 != "") sqlstr += "ar_bez1 LIKE '" + such_ar_bez1.ToSqlString() + "' AND ";

Neu : if (such_ar_bez1 != "") qry = qry.ar_bez1().IsLike(such_ar_bez1).And();


Das ist jetzt ein eigenes ORM, jetzt würde ich aber Dapper oder EF benutzen.

Grüße Bernd

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

2.094 Beiträge seit 2012
vor 2 Jahren

Das ist jetzt ein eigenes ORM, jetzt würde ich aber Dapper oder EF benutzen.

Wobei Dapper aber das SQL schreiben nicht ab nimmt - zumindest nach meinem letzten Stand.
Es mappt nur die Ergebnisse passend zu den eigenen Klassen.
Das übernehmen nur die "großen ORMs" wie EF oder nHibernate, sind dadurch aber auch deutlich komplexer.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

16.864 Beiträge seit 2008
vor 2 Jahren

Wie handhabt ihr Eure SQL Queries?

Wenn es Request Queries sind: alles über EF Core (selten Dapper), sehr viel über entsprechend indizierte Queries.
Wenn es Round Trip Queries sind: über Stored Procs (über EFCore Connection), sofern es MSSQL ist.

Genau über den Weg ist auch das Forum hier umgesetzt; universell einsetzbar.

6.912 Beiträge seit 2009
vor 2 Jahren

Hallo,

auch wenn "Alt" davor steht

  
Alt : if (such_ar_bez1 != "") sqlstr += "ar_bez1 LIKE '" + such_ar_bez1.ToSqlString() + "' AND ";  
  

der dringende Hinweis zu [Artikelserie] SQL: Parameter von Befehlen.
So ist es ein Musterbeispiel für SQL-Injection

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

3.825 Beiträge seit 2006
vor 2 Jahren

So ist es ein Musterbeispiel für
>

Hab ich mir gedacht dass das gleich auffällt.

Das habe ich ungefähr im Jahr 2004 geschrieben, da gab es den guten Artikel noch nicht.

In der Extension 'ToSqlString()' habe ich zwar versucht alles rauszufiltern was zu Fehlern oder Missbrauch führen kann, hat aber nicht immer funktioniert.

Das eigene ORM arbeitet natürlich mit Parametern.

Grüße Bernd

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

4.968 Beiträge seit 2008
vor 2 Jahren

Intern machen die Parameter aber auch nichts anderes als die besonderen Zeichen (z.B. ') zu escapen (habe ich auch schon selber geschrieben).

16.864 Beiträge seit 2008
vor 2 Jahren

Also da passiert schon deutlich mehr als nur Zeichen rausfiltern/escapen....
SqlCommand Source Code
Da wird völlig Typ-gerecht ein vollständiges Cleanup und Aufbau des SQL Befehls vorgenommen.

4.968 Beiträge seit 2008
vor 2 Jahren

Ich meinte konkret den Code zur Umwandlung der Parameter bei der Erzeugung des SQL-Befehls. Dort werden dann u.a. diese Hilfsmethoden aus SqlServerEscapeHelper verwendet:


/// <summary>
///  Escape a string to be used inside TSQL literal, such as N'somename' or 'somename'
/// </summary>
static internal string EscapeStringAsLiteral(string input) {
    Debug.Assert(input != null, "input string cannot be null");
    return input.Replace("'", "''");
}

/// <summary>
/// Escape a string as a TSQL literal, wrapping it around with single quotes.
/// Use this method to escape input strings to prevent SQL injection 
/// and to get correct behavior for embedded quotes.
/// </summary>
/// <param name="input">unescaped string</param>
/// <returns>escaped and quoted literal string</returns>
static internal string MakeStringLiteral(string input) {
    if (ADP.IsEmpty(input)) {
        return "''";
    }
    else {
        return "'" + EscapeStringAsLiteral(input) + "'";
    }
}

Ähnlich sieht es dann bei den anderen Datenbanken (Oracle, PostGres, ...) aus.
Datenbanken nehmen ja (leider) nur direkt SQL-Strings entgegen, d.h. diese müssen vom Client aus zusammengesetzt werden (auch wenn vom Anwender Parameter verwendet werden).