Domanda

Ho una tabella di database chiamata call con colonne call_time, location, emergency_type e ci sono tre tipi di emergenza: paramedici, polizia e vigili del fuoco. Nel modulo di Windows ho creato CheckBox 'paramedics', 'police', 'firefighters' e voglio recuperare tutte le colonne della tabella che soddisfano la selezione dell'utente.

Ho creato una funzione:

public static DataTable GetHistory(DateTime from, DateTime to, bool paramedics, bool police, bool firefighters)
    {
        string select =
            "SELECT call_time, location, emergency_type where call_time between @from AND @to AND";
        if(paramedics)
        {
            select += " emergency_type = 'paramedics' ";
        }
        if(paramedics && police)
        {
           select +=" emergency_type = 'paramedics' OR emergency_type = 'police';
        }
        ...

    }

Questo codice sembra comunque molto sporco perché se ci fossero 30 tipi di emergenza ce ne sarebbero 30! combinazioni e vorrei invecchiare prima di scrivere tutte le dichiarazioni if.

Gradirei se hai condiviso la tua pratica per il recupero di dati che soddisfano le condizioni di ricerca selezionate se ci sono molte opzioni che puoi scegliere.

Grazie!

È stato utile?

Soluzione

Bene, se devi usare emergency_type come stringa, invece di passare i bool potresti inviare un Elenco contenente la rappresentazione testuale del tipo di emergenza. Ad esempio, per modificare il codice sopra puoi cambiare la firma del metodo in

public static DataTable GetHistory(DateTime from, DateTime to, List<string> types)
{
 ..
}

, quindi passa a un elenco simile a questi (ad esempio)

List<string> types = 
  new List<string> { "paramedics" };

or 

List<string> types = 
  new List<string> { "paramedics", "police" };

Quindi è possibile adattare la query per utilizzare l'istruzione SQL IN nella clausola where. Successivamente converti l'elenco di stringhe in una stringa separata da virgola come

string values = "'paramedics', 'police'"

Un modo semplice per creare la variabile valori è utilizzare

string values = string.Empty;
            types.ForEach(s =>
            {
               if (!string.IsNullOrEmpty(values))
                   values += ",";
               values += string.Format("'{0}'", s);

            });

A proposito, è possibile utilizzare un comando con parametri per evitare l'iniezione SQL. Una volta che hai la stringa, puoi semplicemente farlo

string select =
 "SELECT call_time, location, emergency_type where call_time between @from AND @to AND emergency_type IN " + values

Altri suggerimenti

Questo è un modo sporco di farlo.

string select = "SELECT call_time, location, emergency_type where call_time between @from AND @to AND (1=0";

if(paramedics) { select += " OR emergency_type = 'paramedics' "; }
if(police)     { select += " OR emergency_type = 'police'"; }
if(xyz)        { select += " OR emergency_type = 'xyz'"; }

select += ")";

La concatenazione di stringhe dovrebbe essere evitata, in quanto può contribuire ad alcune brutte vulnerabilità. Se stai cercando le migliori pratiche in termini di accesso programmatico, la migliore procedura qui è quella di utilizzare una query con parametri.

Se vuoi essere economico, fai in modo che la clausola in prenda un parametro e concatena quella stringa insieme dall'elenco delle caselle di controllo selezionate e lo passi come valore del parametro per la clausola in. sembrerebbe così:

where ... and emergency_type in (?)

L'altro modo per farlo è contare il numero di caselle di controllo che sono selezionate e costruire l'elenco di parametri nella clausola in, in modo che appaia più simile a questo:

where ... and emergency_type in(?,?...) -- as many params as there are checked checkboxes.

Ognuno di questi andrà bene. Con questi tipi di query, sono arrivato al punto di costruire i miei metodi di costruzione SQL, mantengo un conteggio interno dei parametri e dei loro tipi di dati e costruisco dinamicamente sql, quindi eseguo la preparazione con l'elenco noto di buoni parametri .

Potresti studiare l'apprendimento di Linq.

Crea l'elenco di valori di confronto dell'utente (@EmergencyList) e usa SQL con una query con parametri utilizzando l'operatore Contains.

SELECT call_time, 
       location, 
       emergency_type 
where call_time between @from AND @to 
  AND CONTAINS( Emegency_Type, @EmergencyList )
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top