【问题标题】:SQL Server contains predicate not working with multiple search termsSQL Server 包含的谓词不适用于多个搜索词
【发布时间】:2018-11-28 20:03:55
【问题描述】:

我有一个 C# 程序,它通过用户的输入搜索表。

关键字以空格分隔并保存到数组中。

然后 switch 语句将根据只输入一个词或两个词来选择正确的大小写。

我的 switch 语句只为第一种情况填充我的数据网格,但是当尝试使用第二种情况时,我的程序会进入 catch 异常。

我试过调试,但我唯一看到的是当我进入案例2时,它并没有超越sda1.Fill(dt1);

更新代码:

static string myconnstr = ConfigurationManager.ConnectionStrings["connstrng"].ConnectionString;       

private void btnSearch_Click(object sender, EventArgs e)
{
    //Get the value from textbox
    string keyword = txtboxKeyword.Text;
    string[] words = keyword.Split(' ');

    //SQL Connection
    var conn = new SqlConnection(myconnstr);

    try
    {
        switch (words.Length)
        {
            case 1:
                    //Declare Command object with parameter
                    SqlCommand cmd = new SqlCommand("SELECT Site, StreetAddress, City, State, Zip, PharmacyPhone, MDVersion, InstallDate, SiteCodes, SiteNotActive, CloseDate, SiteNotes " +
                                    "FROM Sites WHERE contains(site, @words0) OR contains (StreetAddress, @words0) OR contains(city, @words0)", conn);

                    cmd.Parameters.AddWithValue("@words0", words[0]);

                    SqlDataAdapter sda = new SqlDataAdapter(cmd);
                    DataTable dt = new DataTable();
                    sda.Fill(dt);
                    dataGridSites.ReadOnly = true;
                    dataGridSites.DataSource = dt;
                    dataGridSites.CurrentCell = null;
                    break;
                case 2:
                    //Declare Command object with parameter
                    SqlCommand cmd1 = new SqlCommand("SELECT Site, StreetAddress, City, State, Zip, PharmacyPhone, MDVersion, InstallDate, SiteCodes, SiteNotActive, CloseDate, SiteNotes " +
                                    "FROM Sites WHERE contains(site, @words0, @words1) OR contains (StreetAddress, @words0, @words1) OR contains(city, @words0, @words1)", conn);

                    cmd1.Parameters.AddWithValue("@words0", words[0]);
                    cmd1.Parameters.AddWithValue("@words1", words[1]);

                    SqlDataAdapter sda1 = new SqlDataAdapter(cmd1);
                    DataTable dt1 = new DataTable();
                    sda1.Fill(dt1);
                    dataGridSites.ReadOnly = true;
                    dataGridSites.DataSource = dt1;
                    dataGridSites.CurrentCell = null;
                    break;                   
        }
    }
    catch (Exception)
    {
        MessageBox.Show("Search cannot be blank.");
    }            
}

这是我得到的更新异常错误:

System.Data.SqlClient.SqlException (0x80131904):附近的语法不正确 '@words1'。错误号:102,状态:1,类:15

【问题讨论】:

  • 获取有关异常的更多信息将对我们有很大帮助,但我之前没有看到 contains() 与“and”一起使用。尝试用contains(city, @words0, @words1)替换contains(city, @words0 and @words1)
  • 我会重新考虑你的方法,我会为每个过滤器实例创建一个有效的方法,然后创建一个Dictionary<string, Func<SqlParameter[], Model>> 来调用字典,其中包含一个要显式执行的方法。然后只需调用您想要的密钥,然后使用.Invoke 执行正确的实现,而不是使用大小写进行切换。在我看来,这将更具表现力。您从过滤器接收数据的有效模型,然后绑定到您的控件。

标签: c# sql-server full-text-search


【解决方案1】:

您现有代码不起作用的原因是contains 不支持您当前尝试调用它的方式的三个参数。

根据documentation,我建议更改:

FROM Sites WHERE contains(site, @words0) OR contains (StreetAddress, @words0) OR contains(city, @words0)

到:

FROM Sites WHERE contains((site, StreetAddress, city), @words0)

还有:

FROM Sites WHERE contains(site, @words0, @words1) OR contains (StreetAddress, @words0, @words1) OR contains(city, @words0, @words1)

到:

FROM Sites WHERE contains((site, StreetAddress, city), @words0) OR contains((site, StreetAddress, city), @words1)

如果你真的想使用当前更冗长的风格,那么Example I 建议:

FROM Sites WHERE contains(site, @wordsConcat) OR contains (StreetAddress, @wordsConcat) OR contains(city, @wordsConcat)

可能工作,其中 @wordsConcat 已(通过 C#)设置为:

words[0] + " OR " + words[1]

【讨论】:

  • 谢谢!我根据您的建议进行了更改,这解决了我的问题。
【解决方案2】:

由于历史原因,我认为这是 switch case 已知的范围问题。这就是为什么我们必须在每个语句之后放置 break。试试看这里。 Variable declaration in a C# switch statement

【讨论】:

  • 您不会在每条语句后添加break。您只需在整个 case 块完成后放置它一次,以防止跌倒。
  • 我不明白这与问题有什么关系。提供的链接(不应将哪些链接用作答案)是指在 switch case 中声明变量,使用与以下 switch case 中声明的其他变量相同的名称。 OP 已经在每个 switch case 中使用了唯一的变量名。
猜你喜欢
  • 1970-01-01
  • 2020-02-06
  • 1970-01-01
  • 1970-01-01
  • 2014-12-11
  • 1970-01-01
  • 1970-01-01
  • 2015-02-05
  • 1970-01-01
相关资源
最近更新 更多