передовой опыт получения данных, соответствующих выбранным условиям

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

  •  05-07-2019
  •  | 
  •  

Вопрос

У меня есть таблица базы данных с именем call со столбцами call_time, location, Emergency_type, и есть три типа чрезвычайной ситуации:парамедики, полиция и пожарные.В форме Windows я создал флажки «парамедики», «полиция», «пожарные» и хочу получить все столбцы таблицы, которые соответствуют выбору пользователя.

Я создал функцию:

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

    }

Однако этот код кажется очень грязным, потому что если бы было 30 видов аварийных ситуаций, их было бы 30!комбинаций, и я бы состарился, прежде чем писать все операторы if.

Буду признателен, если вы поделитесь своей практикой получения данных, соответствующих выбранным условиям поиска, если есть много вариантов, которые вы можете выбрать.

Спасибо!

Это было полезно?

Решение

Что ж, если вам нужно использовать Emergency_type в качестве строки, то вместо передачи логических значений вы можете отправить список, содержащий текстовое представление типа чрезвычайной ситуации.Например, чтобы настроить приведенный выше код, вы можете изменить сигнатуру метода на

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

а затем передать список, который выглядел так (например)

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

or 

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

Затем вы можете адаптировать свой запрос для использования оператора SQL IN в предложенииwhere.Затем преобразуйте список строк в строку, разделенную запятыми, например

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

Простой способ создать переменную значений — использовать

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

            });

Кстати, вы можете использовать параметризованную команду, чтобы избежать внедрения SQL.Если у вас есть строка, вы можете просто сделать

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

Другие советы

Это грязный способ сделать это.

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

Следует избегать конкатенации строк, поскольку она может привести к возникновению некоторых неприятных уязвимостей.Если вы ищете лучшие практики с точки зрения программного доступа, то лучше всего использовать параметризованный запрос.

Если вы хотите сэкономить, тогда пусть предложение in принимает параметр, объединяет эту строку из списка отмеченных флажков и передает его как значение параметра для предложения in.это будет выглядеть так:

where ... and emergency_type in (?)

Другой способ сделать это — подсчитать количество отмеченных флажков и построить список параметров для предложения in, чтобы он выглядел примерно так:

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

Любой из них подойдет.С этими типами запросов я зашел так далеко, что создал свои собственные методы конструктора SQL, я веду внутренний подсчет параметров и их типов данных и динамически создаю sql, а затем выполняю подготовку с известным списком хороших параметров. .

Вы можете изучить Linq.

Создайте пользовательский список значений сравнения (@EmergencyList) и используйте SQL с параметризованным запросом с помощью оператора «Содержит».

SELECT call_time, 
       location, 
       emergency_type 
where call_time between @from AND @to 
  AND CONTAINS( Emegency_Type, @EmergencyList )
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top