SQL inline è ancora classificato come una cattiva pratica ora che abbiamo Micro ORM?

25

Questa è una domanda a risposta aperta, ma volevo delle opinioni, essendo cresciuto in un mondo in cui gli script SQL inline erano la norma, quindi eravamo tutti molto consapevoli dei problemi di SQL injection e della loro fragilità sql era quando facevo manipolazioni di stringhe dappertutto.

Poi è arrivata l'alba dell'ORM in cui stavi spiegando la query all'ORM e permettendogli di generare il suo SQL, che in molti casi non era ottimale ma era sicuro e facile. Un altro aspetto positivo degli ORM o dei livelli di astrazione del database era che l'SQL era stato creato tenendo presente il suo motore di database, quindi potevo usare Hibernate / Nhibernate con MSSQL, MYSQL e il mio codice non era mai cambiato era solo un dettaglio di configurazione.

Ora procediamo velocemente al giorno corrente, dove i Micro ORM sembrano conquistare più sviluppatori mi chiedevo perché abbiamo apparentemente fatto un'inversione a U sull'intero argomento sql in linea.

Devo ammettere che mi piace l'idea di non avere file di configurazione ORM e di poter scrivere la mia query in modo più ottimale, ma mi sembra di tornare alle vecchie vulnerabilità come SQL injection e sono anche io legarmi ad un unico motore di database, quindi se voglio che il mio software supporti più motori di database, dovrei fare un po 'di hackeraggio delle stringhe che sembra iniziare a rendere il codice illeggibile e più fragile. (Poco prima che qualcuno lo menzioni, so che è possibile utilizzare argomenti basati su parametri con la maggior parte dei micro orms che offre protezione nella maggior parte dei casi da SQL injection)

Quindi quali sono le opinioni delle persone su questo genere di cose? Sto usando Dapper come il mio Micro ORM in questa istanza e NHibernate come il mio normale ORM in questo scenario, tuttavia la maggior parte in ogni campo è abbastanza simile.

Quello che definisco inline sql è stringhe SQL all'interno del codice sorgente. Ci sono stati dibattiti di progettazione su stringhe SQL nel codice sorgente che hanno sminuito l'intento fondamentale della logica, motivo per cui le query di stile linq tipizzate in modo statico sono diventate così popolari la sua ancora solo 1 lingua, ma con diciamo C # e Sql in una sola pagina 2 lingue mescolate nel tuo codice sorgente non elaborato ora. Giusto per chiarire, l'iniezione SQL è solo uno dei problemi noti con l'uso di stringhe sql, ho già detto che è possibile impedire che questo accada con query basate su parametri, tuttavia evidenzi altri problemi relativi all'invio di query SQL nel codice sorgente, come la mancanza dell'astrazione di DB Vendor e la perdita di qualsiasi livello di errore in fase di compilazione durante l'acquisizione di query basate su stringhe, sono tutti problemi che siamo riusciti ad affrontare con l'alba degli ORM con le loro funzionalità di query di livello superiore, come HQL o LINQ ecc. (non tutti i problemi ma la maggior parte di essi).

Quindi sono meno focalizzato sui singoli problemi evidenziati e più l'immagine più grande di è ora più accettabile avere stringhe SQL direttamente nel codice sorgente di nuovo, come la maggior parte dei Micro ORM usano questo meccanismo.

Ecco una domanda simile che ha alcuni punti di vista diversi, sebbene si tratti più della sql in linea senza il contesto micro o mmm:

link

    
posta Grofit 16.10.2013 - 16:04
fonte

3 risposte

31

Quello che stai descrivendo come "Inline SQL" dovrebbe essere chiamato "concatenazione di stringhe senza parametrizzazione", e non devi farlo per usare un Micro ORM in sicurezza.

Considera questo esempio di Dapper:

string sql = "SELECT * from user_profile WHERE FirstName LIKE @name;";
var result = connection.Query<Profile>(sql, new {name = "%"+name+"%"});

È completamente parametrizzato, anche se la concatenazione di stringhe è in corso. Vedi il segno @?

O questo esempio:

var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", 
          new { Age = (int?)null, Id = guid });

che è approssimativamente equivalente al seguente codice ADO.NET:

List<Dog> dog = new List<Dog>();
using(var cmd = connection.CreateCommand()) {
    cmd.CommandText = "select Age = @Age, Id = @Id";
    cmd.Parameters.AddWithValue("Age", DBNull.Value);
    cmd.Parameters.AddWithValue("Id", guid);
    using(var reader = cmd.ExecuteReader()) {
        while(reader.Read()) {
            int age = reader.ReadInt32("Age");
            int id = reader.ReadInt32("Id");
            dog.Add(new Dog { Age = age, Id = id });
        }
    }
}

Se hai bisogno di più flessibilità di questo, Dapper fornisce modelli SQL e una funzione AddDynamicParms() . Tutto sicuro per SQL Injection.

Allora perché usare le stringhe SQL in primo luogo?

Bene, per gli stessi motivi si usa SQL personalizzato in qualsiasi altro ORM. Forse l'ORM è un codice SQL non ottimale per la generazione del codice e devi ottimizzarlo. Forse vuoi fare qualcosa che è difficile da fare in ORM in modo nativo, come UNION. O forse vuoi semplicemente evitare la complessità di generare tutte quelle classi proxy.

Se davvero non vuoi scrivere una stringa SQL per ogni metodo CRUD in Dapper ( chi lo fa?), puoi usare questa libreria:

link

Questo ti renderà estremamente semplice e intuitivo CRUD, pur continuando a darti la flessibilità delle istruzioni SQL scritte a mano. Ricorda, l'esempio di ADO.NET sopra era il modo in cui tutti lo facevano prima che arrivasse ORM; Dapper è solo un rivestimento sottile su quello.

    
risposta data 16.10.2013 - 17:06
fonte
1

Le query parametrizzate e il modello di progettazione del repository offrono il pieno controllo su ciò che entra nella query per prevenire attacchi di tipo injection. Inline SQL in questo caso non è un problema diverso dalla leggibilità per query complesse e complesse, che dovrebbero comunque essere in stored procedure.

    
risposta data 02.12.2015 - 22:24
fonte
1

Mi piace sql e non potevo sopportare di vederlo ritagliato in stringhe letterali, quindi ho scritto una piccola estensione VS per permetterti di lavorare con file sql reali in progetti c #. La modifica di sql nel proprio file ti dà intellisense per colonne e tabelle, convalida della sintassi, esecuzione del test, piani di esecuzione e il resto. Quando si salva il file, la mia estensione genera classi wrapper c #, quindi non si scrive mai una riga di codice di connessione, o codice comando, o parametro o codice lettore. Le tue query sono tutte parametrizzate perché non c'è altro modo, e hai generato repository e POCO per il test delle unità, con intellisense per i tuoi parametri di input e i tuoi risultati.

E ho lanciato coltelli da bistecca gratuiti ... Quando un esperto ha bisogno di venire a rielaborare la sql dello sviluppatore, sta guardando un vero file sql e non ha bisogno di toccare alcun C #. Quando torna indietro e riordina il DB, eliminando alcune colonne, i riferimenti alle colonne mancanti vengono visualizzati direttamente come errori di compilazione nel c #. Il database diventa proprio come un altro progetto nella tua soluzione che puoi hackerare, la sua interfaccia è individuabile nel codice. Se la soluzione viene compilata, sai che tutte le tue query funzionano. Non ci sono errori di runtime dovuti a cast non validi o nomi di colonne non validi o query non valide.

Guardando al dapper, che stiamo ancora utilizzando al lavoro, non posso credere che nel 2016 questa sia la cosa più bella nell'accesso ai dati. La generazione del ms di runtime è intelligente, ma tutti gli errori sono errori di runtime e la manipolazione delle stringhe, come la manipolazione delle stringhe per qualsiasi altro scopo, richiede tempo, è fragile e soggetta a errori. E come può essere Dry dover ripetere i nomi delle colonne nel tuo POCO, che devi scrivere e mantenere a mano.

Quindi eccoti. Se vuoi vedere una tecnologia di accesso ai dati sconosciuta da uno sviluppatore inaudito che lavora nel suo tempo libero (con un bambino piccolo e molti altri hobby), è qui .

    
risposta data 27.05.2016 - 15:29
fonte

Leggi altre domande sui tag