meilleure pratique pour récupérer des données qui remplissent certaines conditions

StackOverflow https://stackoverflow.com/questions/255642

  •  05-07-2019
  •  | 
  •  

Question

J'ai une table de base de données appelée call avec les colonnes call_time, location, emergency_type et il existe trois types d'urgence: les ambulanciers paramédicaux, la police et les pompiers. Dans le formulaire Windows, j'ai créé CheckBox 'Ambulanciers', 'Police', 'Pompiers' et je souhaite récupérer toutes les colonnes du tableau qui correspondent à la sélection de l'utilisateur.

J'ai créé une fonction:

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';
        }
        ...

    }

Ce code semble cependant très sale car s’il y avait 30 types d’urgence, il y en aurait 30! combinaisons et je deviendrais vieux avant d'écrire toutes les déclarations si.

Je vous serais reconnaissant de partager votre pratique en matière de récupération de données répondant aux critères de recherche sélectionnés, s’il existe de nombreuses options que vous pouvez choisir.

Merci!

Était-ce utile?

La solution

Eh bien, si vous devez utiliser emergency_type en tant que chaîne, au lieu de transmettre des caractères booléens, vous pouvez envoyer une liste contenant la représentation textuelle du type d'urgence. Par exemple, pour ajuster le code ci-dessus, vous pouvez changer la signature de la méthode en

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

puis transmettez une liste semblable à celle-ci (par exemple)

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

or 

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

Ensuite, vous pouvez adapter votre requête à l’utilisation de l’instruction SQL IN de votre clause where. Ensuite, convertissez la liste de chaînes en chaînes séparées par des virgules, comme

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

Un moyen simple de créer la variable de valeurs consiste à utiliser

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

            });

À propos, vous pouvez utiliser une commande paramétrée pour éviter l’injection SQL. Une fois que vous avez la chaîne, vous pouvez simplement faire

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

Autres conseils

C’est une mauvaise façon de faire cela.

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 concaténation de chaînes doit être évitée car elle peut contribuer à certaines vulnérabilités désagréables. Si vous recherchez les meilleures pratiques en termes d'accès par programme, la meilleure pratique consiste à utiliser une requête paramétrée.

Si vous voulez être bon marché, faites en sorte que la clause in prenne un paramètre, concaténez cette chaîne à partir de la liste des cases à cocher cochées et transmettez-la comme valeur du paramètre de la clause in. cela ressemblerait à ceci:

where ... and emergency_type in (?)

L’autre méthode consiste à compter le nombre de cases à cocher cochées et à créer la liste des paramètres de la clause in afin qu’elle ressemble davantage à ceci:

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

L'un ou l'autre fera très bien l'affaire. Avec ces types de requêtes, je suis allé jusqu'à construire mes propres méthodes de constructeur SQL, je garde un nombre interne de paramètres, ainsi que leurs types de données, et crée dynamiquement le SQL, puis prépare avec la liste connue des bons paramètres. .

Vous pourriez étudier l'apprentissage de Linq.

Construisez la liste des valeurs de comparaison de l'utilisateur (@EmergencyList) et utilisez SQL avec une requête paramétrée à l'aide de l'opérateur Contains.

SELECT call_time, 
       location, 
       emergency_type 
where call_time between @from AND @to 
  AND CONTAINS( Emegency_Type, @EmergencyList )
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top