【问题标题】:best practice for retrieving data which meet selected conditions检索满足选定条件的数据的最佳实践
【发布时间】:2008-11-01 08:14:04
【问题描述】:

我有一个名为 call 的数据库表,其中包含 call_time、location、emergency_type 列,并且紧急情况分为三种类型:护理人员、警察和消防员。在 windows 窗体中,我创建了 CheckBoxes 'paramedics'、'police'、'firefighters',我想检索所有符合用户选择的表列。

我创建了一个函数:

public static DataTable GetHistory(DateTime from, DateTime to, bool paramedics, bool police, bool firefighters)
    {
        string select =
            "SELECT call_time, location, emergency_type where call_time between @from AND @to AND";
        if(paramedics)
        {
            select += " emergency_type = 'paramedics' ";
        }
        if(paramedics && police)
        {
           select +=" emergency_type = 'paramedics' OR emergency_type = 'police';
        }
        ...

    }

然而,这段代码看起来很脏,因为如果有 30 种紧急情况,就会有 30 种!组合,我会在写所有 if 语句之前变老。

如果您能分享您在有很多选项可以选择的情况下检索满足所选搜索条件的数据的做法,我将不胜感激。

谢谢!

【问题讨论】:

  • 顺便说一句,如果语句一个接一个地运行,所以如果护理人员和警察都是真的,那么你最终会得到一个字符串 "...emergency_type = 'paramedics' Emergency_type = 'paramedics' OR Emergency_type = '警察”
  • 这只是一个方法示例,而不是工作版本。

标签: c# .net sql datatable


【解决方案1】:

如果你必须使用emergency_type 作为字符串,那么你可以发送一个包含紧急类型的文本表示的列表,而不是传入布尔值。例如,要调整上述代码,您可以将方法签名更改为

public static DataTable GetHistory(DateTime from, DateTime to, List<string> types)
{
 ..
}

然后传入一个看起来像这样的列表(例如)

List<string> types = 
  new List<string> { "paramedics" };

or 

List<string> types = 
  new List<string> { "paramedics", "police" };

然后您可以调整查询以在 where 子句中使用 SQL IN 语句。接下来将字符串列表转换为逗号分隔的字符串,如

string values = "'paramedics', 'police'"

创建 values 变量的简单方法是使用

string values = string.Empty;
            types.ForEach(s =>
            {
               if (!string.IsNullOrEmpty(values))
                   values += ",";
               values += string.Format("'{0}'", s);

            });

顺便说一句,您可以使用参数化命令来避免 SQL 注入。一旦你有了字符串,你就可以简单地做

string select =
 "SELECT call_time, location, emergency_type where call_time between @from AND @to AND emergency_type IN " + values

【讨论】:

  • 我非常喜欢这种方法,假设所有条件都在同一列上。
【解决方案2】:

这是一种肮脏的做法。

string select = "SELECT call_time, location, emergency_type where call_time between @from AND @to AND (1=0";

if(paramedics) { select += " OR emergency_type = 'paramedics' "; }
if(police)     { select += " OR emergency_type = 'police'"; }
if(xyz)        { select += " OR emergency_type = 'xyz'"; }

select += ")";

【讨论】:

    【解决方案3】:

    应避免字符串连接,因为它可能会导致一些令人讨厌的漏洞。 如果您正在寻找编程访问方面的最佳做法,那么这里的最佳做法是使用参数化查询。

    如果你想便宜,那么让 in 子句接受一个参数,并将该字符串从选中的复选框列表中连接在一起,并将其作为 in 子句的参数值传递。它看起来像这样:

    where ... and emergency_type in (?)
    

    另一种方法是计算被选中的复选框的数量,并为 in 子句构建参数列表,使其看起来更像这样:

    where ... and emergency_type in(?,?...) -- as many params as there are checked checkboxes.
    

    其中任何一个都可以。 使用这些类型的查询,我已经构建了自己的 SQL 构造函数方法,我保留了参数的内部计数及其数据类型,并动态构建 sql,然后使用已知的好参数列表进行准备.

    你可以看看学习 Linq。

    【讨论】:

      【解决方案4】:

      构建用户的比较值列表 (@EmergencyList),并使用包含运算符的参数化查询使用 SQL。

      SELECT call_time, 
             location, 
             emergency_type 
      where call_time between @from AND @to 
        AND CONTAINS( Emegency_Type, @EmergencyList )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-19
        • 2018-09-25
        • 2013-04-29
        • 1970-01-01
        • 2010-09-27
        相关资源
        最近更新 更多