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

时间:2018-12-25 20:00:27

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

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

例如:

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 :(得分:1)

与往常一样,将其分解为更小的位数可以使生活更轻松。不要编写过多的方法,将其分解为较小的部分。

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

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

答案 1 :(得分:1)

您希望您的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等。

答案 2 :(得分:1)

我会做一些类似于kowie le roux建议的事情,只是我相信参数为零,而不是数据库中的值。因此,如果您使用yoda表示法和“ in”子句,则我认为如果指定的字段匹配或提供了零值,则可以使where条件为true。

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

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