from - sqlcommand datatable c#
la mejor práctica para recuperar datos que cumplen con las condiciones seleccionadas (4)
Tengo una tabla de base de datos llamada call con columnas call_time, location, emergency_type y hay tres tipos de emergencia: paramédicos, policías y bomberos. En el formulario de Windows creé CheckBoxes ''paramédicos'', ''policía'', ''bomberos'' y quiero recuperar todas las columnas de la tabla que cumplen con la selección del usuario.
Creé 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 me haría viejo antes de escribir todas las declaraciones if.
Agradecería que compartieras tu práctica para recuperar datos que cumplan con las condiciones de búsqueda seleccionadas si hay muchas opciones que puedes elegir.
¡Gracias!
Esta es una manera 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 += ")";
La concatenación de cadenas debe evitarse, ya que puede contribuir a algunas vulnerabilidades desagradables. Si busca las mejores prácticas en términos de acceso programático, la mejor práctica aquí es usar una consulta parametrizada.
Si quiere ser barato, haga que la cláusula in tome un parámetro y concatene esa cadena de la lista de casillas marcadas, y páselo 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 crear la lista de parámetros a la cláusula in, de modo 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 llegado a construir mis propios métodos de constructor SQL, conservo un conteo interno de parámetros y sus tipos de datos, y construyo dinámicamente el sql, luego preparo con la lista conocida de buenos parámetros .
Puede ver aprender Linq.
Bueno, si tiene que usar emergency_type como una cadena, en lugar de pasar bools, puede 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 pasar una lista que se parece a esto (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. Luego convierta la lista de cadenas en una cadena separada por comas como
string values = "''paramedics'', ''police''"
Una forma simple de crear la variable de valores es usar
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 tienes la cadena, simplemente puedes hacer
string select =
"SELECT call_time, location, emergency_type where call_time between @from AND @to AND emergency_type IN " + values
Cree 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 )