【问题标题】:How to filter a query based on dynamic number of parameters如何根据动态参数数量过滤查询
【发布时间】:2018-12-25 20:00:26
【问题描述】:

如何根据用户选择处理查询中的参数组合。

例如:

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 并选择了一个特定的学院然后想选择这个fac 下的所有部门然后dep_code = 0 => 所有部门,所以我想忽略:

" AND dep_code =? "

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


如果用户选择所有三个参数 0 那么我们将包含所有具有 5 个参数的事物。


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

【问题讨论】:

    标签: c# sql .net ado.net parameterized-query


    【解决方案1】:

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

    从那里看,分配看起来是一样的。

    【讨论】:

      【解决方案2】:

      您希望您的 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,则返回具体的camp等。

      【讨论】:

        【解决方案3】:

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

        另外,如果您使用扩展方法,您甚至可以实现流畅的语法,但这并不是必需的:

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

        【讨论】:

        • 非常感谢,但我对这里的查询有点困惑,如果您能用代码进一步阐明这个想法,我将不胜感激☺️
        猜你喜欢
        • 2017-10-30
        • 1970-01-01
        • 2014-12-15
        • 2017-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-10
        • 1970-01-01
        相关资源
        最近更新 更多