【问题标题】:Database Searching with multiple textboxes in Windows Forms在 Windows 窗体中使用多个文本框进行数据库搜索
【发布时间】:2022-10-23 19:49:08
【问题描述】:

我正在使用 c# 和 windows 窗体开发“简历保存和搜索应用程序”。我的问题是当我同时输入电话号码字段和电子邮件字段时,它没有进行正确的搜索。

理论上,当我输入错误的电子邮件并输入正确的电话号码时,数据网格视图不应显示任何信息。但是由于 if 和 else 语句从上到下运行,如果电话号码为真,程序不控制电子邮件字段。我怎样才能解决这个问题?

注意:我将所有“else if”语句更改为“if”语句,但它不起作用。

Screenshot1

Scrensshot2

我的代码:

private void search_Click(object sender, EventArgs e)
{
    ///search in databese
    if (textBox_Name.Text != "")
    {
        showData("SELECT * FROM BILGILER WHERE NAME LIKE'" + textBox_Name.Text + "%'");
    }
    else if (textBox_Surname.Text != "")
    {
        showData("SELECT * FROM BILGILER WHERE SURNAME LIKE'" + textBox_Surname.Text + "%'");
    }
    else if (textBox_Id.Text != "")
    {
        showData("SELECT * FROM BILGILER WHERE ID LIKE'" + textBox_Id.Text + "%'");
    }
    else if (textBox_Phone.Text != "")
    {
        showData("SELECT * FROM BILGILER WHERE PHONE LIKE'" + textBox_Phone.Text + "%'");
    }
    else if (textBox_Email.Text != "")
    {
        showData("SELECT * FROM BILGILER WHERE EMAIL LIKE'" + textBox_Email.Text + "%'");
    }
    else if (comboBox_Gender.Text != "")
    {
        if (comboBox_Gender.Text == "Male")
        {
            showData("SELECT * FROM BILGILER WHERE GENDER LIKE'" + 0 + "%'");
        }
        else if (comboBox_Gender.Text == "Female")
        {
            showData("SELECT * FROM BILGILER WHERE GENDER LIKE'" + 1 + "%'");
        }
    }
    else
    {
        MessageBox.Show("Please enter a information");
    }
}

【问题讨论】:

  • 这是为什么您需要先制定逻辑然后编写代码来具体实现该逻辑的示例。您构建的这些查询都不包含一个以上的过滤器,那么您怎么可能按多列过滤呢?此外,您使用的是if...else if,因此一旦您发现填充了一个过滤器字段,您就会停止查找。如果首先确定了逻辑,你就不可能编写代码来做这些事情。您可能仍然无法编写所需的代码,但您不会编写执行无意义的代码的代码。在你知道它必须做什么之前不要编写任何代码。
  • 将您的程序与 Olivier Jacot-Descombes 的答案进行比较。

标签: c# if-statement


【解决方案1】:

如果要一次执行多个过滤器,则必须在单个 SELECT 命令中包含所有过滤器并动态构造 WHERE 子句。我通过向StringBuilder 添加术语来做到这一点。

通过使用一些辅助函数,任务变得更容易。它们既可以实现为本地函数(在search_Click 内),也可以实现为单独的方法。

static void AddLikeWithAnd(StringBuilder filter, string columnName, string value)
{
    if (value != "") {
        if (filter.Length > 0) {
            filter.Append(" AND ");
        }
        filter.Append(columnName).Append(" LIKE ").Append(AsSqlString(value + "%"));
    }

}

static string AsSqlString(string s)
{
    return "'" + s.Replace("'", "''") + "'";
}

第一个有条件地添加术语,具体取决于文本框是否为空。它还将条款与AND 结合在一起。第二个函数通过处理用双引号转义单引号来创建 SQL 字符串文字。

使用这些辅助方法,您可以编写:

private void search_Click(object sender, EventArgs e)
{
    var filter = new StringBuilder();
    AddLikeWithAnd(filter, "[NAME]", textBox_Name.Text);
    AddLikeWithAnd(filter, "SURNAME", textBox_Surname.Text);
    AddLikeWithAnd(filter, "ID", textBox_Id.Text);
    AddLikeWithAnd(filter, "PHONE", textBox_Phone.Text);
    AddLikeWithAnd(filter, "EMAIL", textBox_Email.Text);

    string genderValue = comboBox_Gender.Text.ToLower() switch {
        "male" => "0",
        "female" => "1",
        _ => ""
    };
    AddLikeWithAnd(filter, "GENDER", genderValue);

    if (filter.Length > 0) {
        string sql = "SELECT * FROM BILGILER WHERE " + filter.ToString();
        showData(sql);
    } else {
        MessageBox.Show("Please enter a information");
    }
}

我还用方括号对列名NAME 进行了转义,因为这是某些 SQL 方言中的保留字。例如。 SQL-Server 和 Access 使用方括号,MySQL 使用反引号和 Oracle 双引号作为转义字符。

使用 textBox_Name.Text = "Joe's Pub"textBox_Email.Text = "joe" 我得到这个 SQL 命令:

SELECT * FROM BILGILER WHERE [NAME] LIKE 'Joe''s Pub%' AND EMAIL LIKE 'joe%'

请注意,您只能将 LIKE 用于文本列。如果例如IDGENDER 是数字列,这不起作用。并且这些值也不能用单引号括起来。


我的答案解决了“使用多个文本框搜索”问题;但是,另一个基本问题是使用字符串连接插入参数值,而不是使用参数化查询。给出了很多答案,也写了很多关于这个主题的文章,所以我不会将它整合到我的答案中。

见:C# using parametrized query


我使用了较新的 C# 功能,例如 switch 表达式。如果您使用较旧的框架版本,您可能必须将<LangVersion>latest</LangVersion> 标记添加到您的项目文件中。见:C# language versioning

【讨论】:

  • 总的来说,这里的想法是好的。但是我们仍然应该使用参数化查询。而不是附加用户输入。即使我们抛开它的 SQL 注入攻击方面(毕竟它是一个 Win Forms 应用程序),我们也无法利用现有的查询计划,除非它被正确参数化。这种构建动态 SQL 的模式要正确处理有点棘手,这就是为什么有像 SqlKata 这样的库来使这变得更容易的原因。
  • @mason, s.Replace("'", "''") 使注入攻击成为不可能。这必须在showData 中完成,我们不知道其代码。但是,是的,你是对的;但是,一次教初学者太多东西不会有成果。使用 ORM 并使用 LINQ 构造查询会更好。
  • 我理解不希望信息超载的愿望,但是用未参数化的值形成查询是不应该以简单的名义被忽略的事情:重要的是要传达这是正确的做法。而且它甚至没有那么难:每次你在 SQL 命令中添加一个过滤器,在参数集合中添加一个对应的参数。这可以防止 SQL 注入攻击并帮助查询正确运行(通过利用现有的查询计划)。这对于初学者来说并不过分。
猜你喜欢
  • 1970-01-01
  • 2012-06-11
  • 1970-01-01
  • 2011-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-18
  • 2014-03-27
相关资源
最近更新 更多