Как отфильтровать запрос по динамическому количеству параметров - PullRequest
0 голосов
/ 25 декабря 2018

Как обрабатывать комбинацию параметров в запросе на основе выбора пользователя.

Например:

public DataTable GetStudents(int fromYear,int toYear,int camp_code,int fac_code,int dep_code)
        {
            StringBuilder cmdTxt = new StringBuilder();
            cmdTxt.Append(" SELECT register_no,name ");
            cmdTxt.Append(" FROM student WHERE year BETWEEN ? AND ? ");
            cmdTxt.Append(" AND camp_code = ?  AND fac_code = ? AND dep_code =? ");//Is a variable

            using (var myIfxCmd = new IfxCommand(cmdTxt.ToString(), con))
            {
                myIfxCmd.CommandType = CommandType.Text;
                myIfxCmd.Parameters.Add("year1", IfxType.Integer);
                myIfxCmd.Parameters.Add("year2", IfxType.Integer);
                if (con.State == ConnectionState.Closed)
                {
                    con.Open();
                }
                myIfxCmd.Parameters[0].Value = fromYear;
                myIfxCmd.Parameters[1].Value = toYear;
                //..............
            }

  • Организация содержит набор лагерей.
  • Лагерь содержит множество факультетов.
  • Факультет содержит множество кафедр.

В этом коде я хочу контролировать (int camp,int fac,int dep).Если пользователь выбирает все лагеря, то camp = 0 => Вся организация, поэтому я хочу игнорировать

" AND camp_code = ?  AND fac_code = ? AND dep_code =? "

И в этом случае у меня есть только два параметра для fromYear,toYear


Если пользователь выбирает определенный camp <> 0 и хочет выбрать все способности, тогда fac_code = 0 => все способности, поэтому я хочу игнорировать:

" AND fac_code = ? AND dep_code =? "

И в этом случае у меня есть только три параметрадля fromYear,toYear,camp_code


Если пользователь выбирает конкретный camp <> 0 и выбирает конкретный факультет, то хочет выбрать все кафедры по этому факультету, тогда dep_code = 0 => все кафедры, поэтому я хочуигнорировать:

" AND dep_code =? "

И в этом случае у меня есть только четыре параметра для fromYear,toYear,camp_code,fac_code


Если пользователь выберет все три аргумента <> 0, то мы включим все, что имеет5 параметров.


Я хочу сделать его динамичным и гибким, чтобы соответствовать этим критериям.Я решаю это, но поражен десятками (IF-ELSE) заявлений.

Ответы [ 3 ]

0 голосов
/ 25 декабря 2018

Вы бы хотели, чтобы ваш SQL выглядел примерно так:

    cmdTxt.Append(" SELECT register_no,name ");
    cmdTxt.Append(" FROM student WHERE year BETWEEN ? AND ? ");
    cmdTxt.Append(" AND (camp_code = ? OR camp_code = 0) AND (fac_code = ? or fac_code = 0) AND (dep_code = ? or dep_code = 0) ");

Вышеприведенное означало бы, что если camp_code равен 0, dep_code равен 0 и fac_code равен 0, все вернется.Если camp_code <> 0, а dep_code и fac_code равны 0, он возвращает определенный лагерь и т. Д.

0 голосов
/ 26 декабря 2018

Я бы сделал нечто похожее на то, что предложил kowie le roux, только я верю, что это параметр , который равен нулю, а не значение в базе данных.Таким образом, если вы используете нотацию yoda и предложение «in», я думаю, вы можете заставить условие where быть истинным, если указанное поле совпадает или задано нулевое значение:

select register_no, name
from student
where
  year between ? and ? and
  ? in (camp_code, 0) and
  ? in (fac_code, 0) and
  ? in (dep_code, 0)

Youнужно будет объявить и назначить все пять параметров.

Кроме того, для чего это стоит, я не знаю, что такое Ifx - Informix?Если так, посмотрите, поддерживает ли он именованные параметры.Если это произойдет, то подобное поможет сделать код более понятным.

string sql = @"
    select register_no, name
    from student
    where
        year between @FROM and @THRU and
        @CAMP in (camp_code, 0) and
        @FAC in (fac_code, 0) and
        @DEP in (dep_code, 0)
";

using (var myIfxCmd = new IfxCommand(sql, con))
{
    myIfxCmd.CommandType = System.Data.CommandType.Text;
    myIfxCmd.Parameters.Add("@FROM", IfxType.Integer);
    myIfxCmd.Parameters.Add("@THRU", IfxType.Integer);
    myIfxCmd.Parameters.Add("@CAMP", IfxType.Integer);
    myIfxCmd.Parameters.Add("@FAC", IfxType.Integer);
    myIfxCmd.Parameters.Add("@DEP", IfxType.Integer);

Оттуда назначения будут выглядеть одинаково.

0 голосов
/ 25 декабря 2018

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

В качестве бонуса, если вы используете методы расширения, вы даже можете добиться свободного синтаксиса, но это не является действительно необходимым:

static IfxCommand GetStudents() { //create unfiltered query here ... }
static IfxCommand FilterByYears(
    this IfxCommand command,
    DateTime start,
    DateTime end) { ... }
 static IfxCommand FilterByCampus(
     this IfxCommand command,
     int campusId) { ... }
  //etc.

Теперь в каждом методе FilterBy... вы изменяете команду соответственно (или нет) и передаете ее.Нет спагетти-кода, каждый метод заботится только об одном фильтре.

И вы легко строите свой запрос:

var command =
   GetStudents().FilterByYears(start, end)
                .FiltersByCampus(campus)
                .FilerByFaculty(fac);
...