las mejores prácticas para recuperar datos que cumplan con las condiciones seleccionadas

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

  •  05-07-2019
  •  | 
  •  

Pregunta

Tengo una tabla de base de datos llamada call con columnas call_time, location, emergency_type y hay tres tipos de emergencias: paramédicos, policías y bomberos. En el formulario de Windows, creé CheckBoxes 'paramédicos', 'police', 'firefighters' y quiero recuperar todas las columnas de la tabla que cumplen con la selección del usuario.

He creado una función:

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

    }

Sin embargo, este código parece muy sucio porque si hubiera 30 tipos de emergencia, ¡habría 30! Combinaciones y envejecería antes de escribir todas las declaraciones if.

Le agradecería que compartiera su práctica para recuperar datos que cumplan con las condiciones de búsqueda seleccionadas si hay muchas opciones que puede elegir.

¡Gracias!

¿Fue útil?

Solución

Bueno, si tiene que usar emergency_type como una cadena, en lugar de pasar bools, podría enviar una Lista que contenga la representación de texto del tipo de emergencia. Por ejemplo, para ajustar el código anterior, puede cambiar la firma del método a

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

y luego pase a una lista que se vea así (por ejemplo)

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

or 

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

Luego, podría adaptar su consulta para usar la instrucción SQL IN en su cláusula where. A continuación, convierta la lista de cadenas en una cadena separada por comas como

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

Una forma sencilla de crear la variable de valores es utilizar

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

            });

Por cierto, podría usar un comando parametrizado para evitar la inyección de SQL. Una vez que tengas la cadena, simplemente puedes hacerlo

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

Otros consejos

Esta es una forma sucia de hacer esto.

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 += ")";

Se debe evitar la concatenación de cadenas, ya que puede contribuir a algunas vulnerabilidades desagradables. Si está buscando las mejores prácticas en términos de acceso programático, la mejor práctica aquí es utilizar una consulta parametrizada.

Si desea ser barato, entonces haga que la cláusula in tome un parámetro y concatene esa cadena de la lista de casillas de verificación marcadas, y pase eso como el valor del parámetro para la cláusula in. se vería así:

where ... and emergency_type in (?)

La otra forma de hacerlo es contar el número de casillas de verificación que están marcadas y construir la lista de parámetros en la cláusula in, para que se vea más como esto:

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

Cualquiera de estos hará bien. Con este tipo de consultas, he ido tan lejos como para construir mis propios métodos de construcción de SQL, mantengo un recuento interno de parámetros y sus tipos de datos, y construyo dinámicamente el SQL, luego hago la preparación con la lista conocida de buenos parámetros. .

Puedes mirar el aprendizaje de Linq.

Construya la lista de valores de comparación del usuario (@EmergencyList) y use SQL con una consulta parametrizada utilizando el operador Contiene.

SELECT call_time, 
       location, 
       emergency_type 
where call_time between @from AND @to 
  AND CONTAINS( Emegency_Type, @EmergencyList )
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top