【问题标题】:Syntax for Multi-Option Search多选项搜索的语法
【发布时间】:2012-04-18 23:14:13
【问题描述】:

ASP.NET 4.0、Web 表单、C#、SQL

我几乎有一些类似于您在约会网站上看到的搜索表单。多个下拉框,每个 ddbox 都有特定的值以及“任何”值。我想不出一种简单的方法来在下面的示例之外创建这种语法,并在按钮单击事件后面的 c# 代码中使用大量 else if 语句:

if
= && = && =
else if<br/>
= && = && !=
else if<br/>
= && != && != 
else if<br/>
!= && = && !=

...这里是带有选定值的相同序列

if
Any && Any && Any
else if
Any && Any && Not Any
else if
Any && Not Any && Not Any
else if
Not Any && Any && Not Any

这种情况一直持续到我遍历所有场景。在按钮上单击后面的代码将采用选定的值并决定执行哪个查询。似乎导致头痛的是 ddbox 中的值“any”。有没有首选的方式来构造 c# 或 sql 语法以减少 else if 的数量?

让我知道这是否有意义或者您是否需要更多信息。

【问题讨论】:

  • 如果您想让数据库及时返回结果,您在寻求索引使用时需要考虑很多因素。您的旅程应该开始阅读以下内容:Dynamic Search Conditions in T-SQL by Erland Sommarskog。这是一篇 SQL Server 文章(您似乎处于“Microsoft”环境中)。如果您正在使用“通用”SQL 来处理任何数据库,那么祝您好运,使用“通用”SQL 并在您的表增长时通过此类搜索获得良好的性能。在不了解数据库的情况下很难调整/优化查询。

标签: c# asp.net sql syntax


【解决方案1】:

我会这样写:

create procedure usp_search (
    @param1 varchar(50) = null
   ,@param2 carchar(50) = null
) as
begin
    select field1
          ,field2
          ,field3
          ,fieldN
      from table t with(nolock)
     where ((@param1 is null) or (t.fieldX == @param1))
       and ((@param2 is null) or (t.fieldY == @param2))
end

然后在你喜欢的客户端上

//code
var connection = new SqlConnection("connection_string");
var command = new SqlCommand();
command.Connection = connection;
command.CommandText = "usp_Search";
command.CommandType = CommandType.StoredProcedure;
if((string.IsNullOrEmpty(stringVariable1)) || (stringVariable2.ToLower().Equals("any"))) {
    command.Parameters.Add("@param1", SqlType.VarChar, 50).Value = DBNull.Value;
} else {
    command.Parameters.Add("@param1", SqlType.VarChar, 50).Value = stringVariable1;
}
if((string.IsNullOrEmpty(stringVariable2)) || (stringVariable2.ToLower().Equals("any"))) {
    command.Parameters.Add("@param2", SqlType.VarChar, 50).Value = DBNull.Value;
} else {
    command.Parameters.Add("@param2", SqlType.VarChar, 50).Value = stringVariable2;
}
// code

沿着这些思路...这样您的搜索查询可以检索过滤或未过滤的结果...当然您必须注意此类查询的一些陷阱

编辑:仅在 C# 代码中完成的相同操作将是这样的:

var sb = new StringBuilder();
sb.Append("select field1 ,field2, field3, fieldN ");
sb.Append("from table t with(nolock) ");
sb.Append("where ((@param1 is null) or (t.fieldX == @param1))");
sb.Append("and ((@param2 is null) or (t.fieldY == @param2))");

var connection = new SqlConnection("connection_string");
var command = new SqlCommand();
command.Connection = connection;
command.CommandText = sb.ToString();
command.CommandType = CommandType.Text;
if((string.IsNullOrEmpty(stringVariable1)) || (stringVariable2.ToLower().Equals("any"))) {
    command.Parameters.Add("@param1", SqlType.VarChar, 50).Value = DBNull.Value;
} else {
    command.Parameters.Add("@param1", SqlType.VarChar, 50).Value = stringVariable1;
}
if((string.IsNullOrEmpty(stringVariable2)) || (stringVariable2.ToLower().Equals("any"))) {
    command.Parameters.Add("@param2", SqlType.VarChar, 50).Value = DBNull.Value;
} else {
    command.Parameters.Add("@param2", SqlType.VarChar, 50).Value = stringVariable2;
}

【讨论】:

  • 谢谢,我会试一试。我在考虑参数行,但不确定如何处理查询的“任何”功能。明天很可能会进行测试...
  • 不幸的是,在过滤方面没有很多选择,到处都是丑陋的if 语句,但是这些方面的东西应该可以工作。告诉我。
【解决方案2】:

首先,我建议在您的下一个项目中考虑使用 ORM,因为动态 sql 在应用程序设计方面有很多此类警告。

也就是说,我处理这个问题的方式是将任何可选的搜索词放在括号内,这样我就可以这样做了:

(SomeField = 'Blah' OR 1=1)

请记住,我并不是说这是一个好的解决方案,但它确实可以让您减少嵌套语句的数量,因为您可以按顺序构造 SQL 语句。

考虑以下代码:

SQL = "SELECT CompanyName, CompanyState FROM Companies WHERE ";
SQL += "(CompanyName = '" & CompanyName & "' " + (CompanyName == "AnyKey" ? " OR 1=1" : "") + ") ";
SQL += "(CompanyState = '" & CompanyState & "' " + (CompanyState == "AnyKey" ? " OR 1=1" : "") + ") ";

再次强调,这不应该被认为是好的。我已经转向 ORM,所以我不再有这个问题了。与往常一样,请务必清理您的用户输入。

希望这会有所帮助。

【讨论】:

  • 谢谢,我明天也试一试,看看效果如何 - 肯定会看 int ORM!
  • 在工作中我使用 LLBLGen,它做得很好,但我们必须围绕它实现一个海量数据层。如果项目很大,请先研究许多 ORM 以及如何使用它们做出决定
猜你喜欢
  • 2011-04-04
  • 1970-01-01
  • 2011-02-16
  • 2018-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-01
相关资源
最近更新 更多