如何根据参数的动态数量过滤查询

How to filter a query based on dynamic number of parameters

如何处理基于用户 selections 的查询中的参数组合。

例如:

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)。 如果用户select所有阵营那么camp = 0 =>整个组织,所以我想忽略

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

在这种情况下,我只有两个参数 fromYear,toYear


如果用户 select 是一个特定的 camp <> 0 并且想要 select 所有院系然后 fac_code = 0 => 所有院系,所以我想忽略:

" AND fac_code = ? AND dep_code =? "

在这种情况下,我只有 fromYear,toYear,camp_code

的三个参数

如果用户 select 是一个特定的 camp <> 0 并且 select 是一个特定的教员然后想要 select 该教员下的所有部门然后 dep_code = 0 = > 所有部门,所以我想忽略:

" AND dep_code =? "

在这种情况下,我只有四个参数 fromYear,toYear,camp_code,fac_code


如果用户 select 所有三个参数 <> 0 那么我们将包括所有具有 5 个参数的东西。


我想让它变得动态和灵活以满足这些标准。我解决了它,但被几十个 (IF-ELSE) 语句淹没了。

一如既往,将其分解成更小的部分会让生活更轻松。不要写太多的方法,把它分解成更小的部分。

作为奖励,如果您使用扩展方法,您甚至可以获得流畅的语法,但这并不是真正必要的:

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);

您希望您的 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,那么都是return。如果camp_code <> 0,且dep_code和fac_code为0,则return特定阵营等

我会做类似于 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)

您需要声明并分配所有五个参数。

此外,就其价值而言,我不知道 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);

作业从那里看起来是一样的。