C# 通过传递多个可为空的值从数据库筛选数据

C# 通过传递多个可为空的值从数据库筛选数据,c#,sql,asp.net,database,C#,Sql,Asp.net,Database,我有一个有n个列的表,我想用n个可为空的参数来过滤数据, 在c#(Linq,Entity framework)或带查询的SQL中,有任何方法可以解决这个问题,而不是写n次if-else条件。 如果任何人有任何解决方案,请举例说明。 谢谢。当然,您可以在该sql中使用可选参数 你是怎么做的?您不在sql中包含参数,然后只在需要时添加参数!这样,您就不需要sql中所有这些额外的条件,也不需要对@Param=null进行测试 所以,假设我可以搜索城市,或者城市+酒店名。让我们加入[x]搜索活动酒店。或

我有一个有n个列的表,我想用n个可为空的参数来过滤数据, 在c#(Linq,Entity framework)或带查询的SQL中,有任何方法可以解决这个问题,而不是写n次if-else条件。 如果任何人有任何解决方案,请举例说明。
谢谢。

当然,您可以在该sql中使用可选参数

你是怎么做的?您不在sql中包含参数,然后只在需要时添加参数!这样,您就不需要sql中所有这些额外的条件,也不需要对@Param=null进行测试

所以,假设我可以搜索城市,或者城市+酒店名。让我们加入[x]搜索活动酒店。或者我们只搜索Hotelname。或全部3个值

正如您所注意到的,这变成了一个harry ball参数,它只需要处理3个选项(6种可能的排列)。我只能想象,如果你有5或6个可能的可选值,情况会变得多么糟糕

那么,简单的解决方案是什么?好的,我们将sql拆分为一个基本查询,然后动态添加参数。我们仍然需要(并获得)强类型参数检查,从而获得sql注入保护,这当然是这里的一个重要目标

因此,我们有以下设置:

然后搜索会执行以下操作:

public void loadgrid()
{
string strSQL;
string strWhere;
strSQL = "select ID, FirstName, LastName, HotelName, City, Province from tblHotels";
strWhere = "";

using (SqlCommand cmdSQL = new SqlCommand(strSQL, new SqlConnection(My.Settings.Test3)))
{
    if (txtHotelName.Text != "")
    {
        // search for hotel name
        strWhere = "(HotelName = @HotelName)";
        cmdSQL.Parameters.Add("@HotelName", SqlDbType.NVarChar).Value = txtHotelName.Text;
    }

    if (txtCity.Text != "")
    {
        if (strWhere != "")
            strWhere += " AND ";
        strWhere += "(City = @City)";
        cmdSQL.Parameters.Add("@City", SqlDbType.NVarChar).Value = txtCity.Text;
    }

    if (chkOnlyActive.Checked == true)
    {
        if (strWhere != "")
            strWhere += " AND ";
        strWhere += strWhere + "(HotelActive = @Active)";
        cmdSQL.Parameters.Add("@Active", SqlDbType.Bit).Value = 1;
    }

    if (strWhere != "")
        cmdSQL.CommandText = strSQL + " WHERE " + strWhere;

    cmdSQL.Connection.Open();
    DataTable rstData = new DataTable();
    rstData.Load(cmdSQL.ExecuteReader);

    ListView1.DataSource = rstData;
    ListView1.DataBind();
}
}
所以请注意我们是如何简单地构建where子句的。您注意到,没有任何东西可以阻止我们更改sql命令文本,我们也可以100%地动态添加参数(添加参数不会强制对sql进行检查),只在执行时进行

结果呢?我们可以再添加5个条件。它们是可选的,它们不需要我们使用大量我们可能不想使用甚至不需要的参数来进行大型长sql查询

如上所示,我们从来并没有用户输入的串接——它们总是只用于参数值

因此,对于任何文本框、复选框、组合框或任何东西,我们只需在未填写时忽略它们。因此,它们都是可选的,在我们的代码中被忽略了很多。因此,上述设置允许我们轻松添加2或5个可选参数

IList<ThingToQuery> things = new List<ThingToQuery>();
things.Add(new ThingToQuery(){ Property1 = "Thing1", Property2 = 100, Property3 = new DateTime(2001,1,1)});
things.Add(new ThingToQuery() { Property1 = "Thing2", Property2 = 100, Property3 = new DateTime(2002, 2, 2) });
things.Add(new ThingToQuery() { Property1 = "Thing3", Property2 = 300, Property3 = new DateTime(2003, 3, 3) });

// query sample #1 - prepare params
string queryParam1 = "Thing1";
int? queryParam2 = 100;
DateTime? queryParam3 = null;

// in our query we check for a matching value or if the param is null
List<ThingToQuery> results = things.Where(t => (t.Property1 == queryParam1 || queryParam1 == null)
                                          && (t.Property2 == queryParam2 || queryParam2 == null)
                                          && (t.Property3 == queryParam3 || queryParam3 == null)
            ).ToList();

// query sample #1 results
// Thing1, 100, 1/1/2001 12:00:00 AM

// query sample #2 - prepare params
string queryParam1 = null;
int? queryParam2 = 100;
DateTime? queryParam3 = null;

// query sample #2 results
// Thing1, 100, 1/1/2001 12:00:00 AM
// Thing2, 100, 2/2/2002 12:00:00 AM

注意,在上面,我们总是“检查”where子句是否已经有一些值,如果有,那么我们会在前面添加“and”子句。我们可以在这里使用“OR”,但这取决于您想要的搜索类型。

当然,您可以在该sql中使用可选参数

您这样做的方式?您不需要在sql中包含参数,然后只在需要时添加参数!这样,您就不需要sql中所有这些额外的条件,即条件,然后还需要对@Param=null进行测试

所以,假设我可以搜索City,或者City+HotelName。让我们只搜索[x]个活动酒店。或者我们只搜索HotelName。或者全部3个值

正如您所注意到的,这变成了一个harry ball的参数,它只需要处理3个选项(6个可能的排列)。我只能想象,如果您有5个或6个可能的可选值,这会变得多么糟糕

那么,简单的解决方案是什么呢?好吧,我们将sql拆分为一个基本查询,然后动态添加参数。我们仍然需要(并获得)强类型参数检查,从而获得sql注入保护,这当然是这里的一个重要目标

因此,我们有以下设置:

然后搜索会执行以下操作:

public void loadgrid()
{
string strSQL;
string strWhere;
strSQL = "select ID, FirstName, LastName, HotelName, City, Province from tblHotels";
strWhere = "";

using (SqlCommand cmdSQL = new SqlCommand(strSQL, new SqlConnection(My.Settings.Test3)))
{
    if (txtHotelName.Text != "")
    {
        // search for hotel name
        strWhere = "(HotelName = @HotelName)";
        cmdSQL.Parameters.Add("@HotelName", SqlDbType.NVarChar).Value = txtHotelName.Text;
    }

    if (txtCity.Text != "")
    {
        if (strWhere != "")
            strWhere += " AND ";
        strWhere += "(City = @City)";
        cmdSQL.Parameters.Add("@City", SqlDbType.NVarChar).Value = txtCity.Text;
    }

    if (chkOnlyActive.Checked == true)
    {
        if (strWhere != "")
            strWhere += " AND ";
        strWhere += strWhere + "(HotelActive = @Active)";
        cmdSQL.Parameters.Add("@Active", SqlDbType.Bit).Value = 1;
    }

    if (strWhere != "")
        cmdSQL.CommandText = strSQL + " WHERE " + strWhere;

    cmdSQL.Connection.Open();
    DataTable rstData = new DataTable();
    rstData.Load(cmdSQL.ExecuteReader);

    ListView1.DataSource = rstData;
    ListView1.DataBind();
}
}
请注意,我们是如何简单地构建where子句的。您注意到,没有任何东西可以阻止我们更改sql命令文本,而且我们还可以100%地动态添加参数(添加参数不会强制对sql进行检查),仅在执行时进行

结果呢?我们可以再添加5个条件。它们是可选的,它们不需要我们使用大量我们可能不想使用甚至不需要的参数来进行大型长sql查询

如上所示,我们从来并没有用户输入的串接——它们总是只用于参数值

因此,对于任何文本框、复选框、组合框或任何东西,我们只需在未填写时忽略它们。因此,它们都是可选的,在我们的代码中被忽略了很多。因此,上述设置允许我们轻松添加2或5个可选参数

IList<ThingToQuery> things = new List<ThingToQuery>();
things.Add(new ThingToQuery(){ Property1 = "Thing1", Property2 = 100, Property3 = new DateTime(2001,1,1)});
things.Add(new ThingToQuery() { Property1 = "Thing2", Property2 = 100, Property3 = new DateTime(2002, 2, 2) });
things.Add(new ThingToQuery() { Property1 = "Thing3", Property2 = 300, Property3 = new DateTime(2003, 3, 3) });

// query sample #1 - prepare params
string queryParam1 = "Thing1";
int? queryParam2 = 100;
DateTime? queryParam3 = null;

// in our query we check for a matching value or if the param is null
List<ThingToQuery> results = things.Where(t => (t.Property1 == queryParam1 || queryParam1 == null)
                                          && (t.Property2 == queryParam2 || queryParam2 == null)
                                          && (t.Property3 == queryParam3 || queryParam3 == null)
            ).ToList();

// query sample #1 results
// Thing1, 100, 1/1/2001 12:00:00 AM

// query sample #2 - prepare params
string queryParam1 = null;
int? queryParam2 = 100;
DateTime? queryParam3 = null;

// query sample #2 results
// Thing1, 100, 1/1/2001 12:00:00 AM
// Thing2, 100, 2/2/2002 12:00:00 AM

注意,在上面,我们总是“检查”where子句是否已经有一些值,如果有,那么我们在前面添加“and”子句。我想我们可以使用“OR”这里,但这取决于您想要的搜索类型。

我在SQL语句和LINQ查询中都可以使用的“技巧”是允许查询参数为null,然后检查匹配值或每个参数为null

我们将参数设置为null,并根据各自的字段/属性检查每个参数是否为null

基本上,我们告诉查询提供输入参数与属性值匹配的所有记录,如果输入参数为null,我们会短路该参数,从而导致查询忽略该参数。这有效地提供了一个参数,该参数在为null时视为可选,否则不可选

使用此方法可以轻松添加更多可选参数

IList<ThingToQuery> things = new List<ThingToQuery>();
things.Add(new ThingToQuery(){ Property1 = "Thing1", Property2 = 100, Property3 = new DateTime(2001,1,1)});
things.Add(new ThingToQuery() { Property1 = "Thing2", Property2 = 100, Property3 = new DateTime(2002, 2, 2) });
things.Add(new ThingToQuery() { Property1 = "Thing3", Property2 = 300, Property3 = new DateTime(2003, 3, 3) });

// query sample #1 - prepare params
string queryParam1 = "Thing1";
int? queryParam2 = 100;
DateTime? queryParam3 = null;

// in our query we check for a matching value or if the param is null
List<ThingToQuery> results = things.Where(t => (t.Property1 == queryParam1 || queryParam1 == null)
                                          && (t.Property2 == queryParam2 || queryParam2 == null)
                                          && (t.Property3 == queryParam3 || queryParam3 == null)
            ).ToList();

// query sample #1 results
// Thing1, 100, 1/1/2001 12:00:00 AM

// query sample #2 - prepare params
string queryParam1 = null;
int? queryParam2 = 100;
DateTime? queryParam3 = null;

// query sample #2 results
// Thing1, 100, 1/1/2001 12:00:00 AM
// Thing2, 100, 2/2/2002 12:00:00 AM

可以在SQL语句和LINQ查询中使用的“技巧”是允许查询参数为null,然后检查每个参数的匹配值或null

我们将参数设置为null,并根据各自的字段/属性检查每个参数是否为null

基本上,我们告诉查询提供输入参数与属性值匹配的所有记录,如果输入参数为null,我们会短路该参数,从而导致查询忽略该参数。这有效地提供了一个参数,该参数在为null时视为可选,否则不可选

Usi