【问题标题】:Does Dapper support the like operator?Dapper 是否支持 like 运算符?
【发布时间】:2011-08-27 04:05:13
【问题描述】:

使用 Dapper-dot-net...

以下内容不会在数据对象中产生结果:

var data = conn.Query(@"
    select top 25 
    Term as Label, 
    Type, 
    ID 
    from SearchTerms 
    WHERE Term like '%@T%'", 
    new { T = (string)term });

但是,当我只使用常规字符串格式时:

string QueryString = String.Format("select top 25 Term as Label, Type, ID from SearchTerms WHERE Term like '%{0}%'", term);
var data = conn.Query(QueryString);

我在集合中恢复了 25 行。 Dapper 是否没有正确解析参数@T 的结尾?

【问题讨论】:

    标签: sql dapper


    【解决方案1】:

    试试:

    term = "whateverterm";
    var encodeForLike = term => term.Replace("[", "[[]").Replace("%", "[%]");
    
    string term = "%" + encodeForLike(term) + "%";
    var data = conn.Query(@"
       select top 25 
      Term as Label, 
      Type, 
      ID 
      from SearchTerms 
      WHERE Term like @term", 
      new { term });
    

    like 运算符没有什么特别之处,你永远不会希望你的参数在字符串文字中,它们不会起作用,而是会被解释为字符串。

    注意

    强烈建议不要使用第二个 sn-p 中的硬编码示例,除了是 sql 注入的一个大问题之外,它还可能导致 dapper 泄漏。

    警告

    任何以通配符开头的 like 匹配都不是 SARGable,这意味着它很慢并且需要索引扫描。

    【讨论】:

    • Sam - 试图让你的答案在我的项目中工作,但抛出错误。为什么在将其声明为字符串之前设置“术语”?我只需要查询中术语右侧的 % 。我试过这样做: string formattedTerm = searchTerm + "[[]%[]]";但它没有返回结果。
    • Sam - 可能值得回答他。这也让我感到困惑
    • .Replace("[", "[[]").Replace("]","[]]") - 这是错误的。不过,请确保您避开了您的 like 子句:stackoverflow.com/questions/439495/…
    • 注意:这种方法容易受到 SQL 注入攻击,请查看 Atir 的答案以获得更好的方法
    • 对于不了解“SARGable”的任何人(如我),here is an explanation
    【解决方案2】:

    使用它在查询中添加 concat 函数的最佳方法,因为它也保存在 sql 注入中,但 concat 函数仅支持高于 sql 2012

    string query = "SELECT * from country WHERE Name LIKE CONCAT('%',@name,'%');"
    var results = connection.query<country>(query, new {name});
    

    【讨论】:

    • 您也可以使用 '+' 代替 CONCAT 例如:“SELECT * from country WHERE Name LIKE '%' + @name + '%';”
    【解决方案3】:

    是的。这个简单的解决方案每次都对我有用:

    db.Query<Remitente>("SELECT * 
                         FROM Remitentes 
                         WHERE Nombre LIKE @n", new { n = "%" + nombre + "%" })
                       .ToList();
    

    【讨论】:

    • 这是我最喜欢的答案...简单直接
    • 这肯定是我最喜欢的 - 我也使用字符串插值,所以它变成了 ... new { n = $"%{nombre}%" }
    • 完美!用它制作了 ext 方法
    • 应该是公认的答案
    【解决方案4】:

    Sam 的回答对我不起作用,所以经过一些测试后,我想出了使用 SQLite CONCAT equivalent 似乎有效的方法:

    string sql = "SELECT * FROM myTable WHERE Name LIKE '%' || @NAME || '%'";
    var data = IEnumerable data = conn.Query(sql, new { NAME = Name });
    

    【讨论】:

      【解决方案5】:

      为了偏离 Sam 的回答,这里是我创建两个辅助方法以使用 LIKE 运算符使搜索更容易一些的方法。

      首先,创建一个用于生成参数化查询的方法,该方法使用 dynamic: ,但是在许多需要静态类型而不是动态类型的情况下,应该更希望创建一个强类型的泛型方法。

      public static dynamic ParameterizedQuery(this IDbConnection connection, string sql, Dictionary<string, object> parametersDictionary)
      {
          if (string.IsNullOrEmpty(sql))
          {
              return null;
          }
          string missingParameters = string.Empty;
          foreach (var item in parametersDictionary)
          {
              if (!sql.Contains(item.Key))
              {
                  missingParameters += $"Missing parameter: {item.Key}";
              }
          }
          if (!string.IsNullOrEmpty(missingParameters))
          {
              throw new ArgumentException($"Parameterized query failed. {missingParameters}");
          }
          var parameters = new DynamicParameters(parametersDictionary);
          return connection.Query(sql, parameters);
      }
      

      然后添加一个方法来创建一个适用于 Dapper 的 Like 搜索词。

      public static string Like(string searchTerm)
      {
          if (string.IsNullOrEmpty(searchTerm))
          {
              return null;
          }
          Func<string, string> encodeForLike = searchTerm => searchTerm.Replace("[", "[[]").Replace("%", "[%]");
          return $"%{encodeForLike(searchTerm)}%";
      }
      

      示例用法:

      var sql = $"select * from products where ProductName like @ProdName";
      var herringsInNorthwindDb = connection.ParameterizedQuery(sql, new Dictionary<string, object> { { "@ProdName", Like("sild") } });
      
      foreach (var herring in herringsInNorthwindDb)
      {
          Console.WriteLine($"{herring.ProductName}");
      }
      

      我们从 Northwind DB 获取样本数据:

      我喜欢这种方法,因为我们使用辅助扩展方法来完成重复性工作。

      【讨论】:

        【解决方案6】:

        我对这个问题的解决方案很简单:

        parameter.Add("@nomeCliente", dfNomeCliPesquisa.Text.ToUpper());
        
        query = "SELECT * FROM cadastrocliente WHERE upper(nome) LIKE " + "'%" + dfNomeCliPesquisa.Text.ToUpper() + "%'"; 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-06-29
          • 1970-01-01
          • 2012-04-25
          • 2012-02-11
          • 2011-07-25
          • 2014-05-28
          相关资源
          最近更新 更多