代码之家  ›  专栏  ›  技术社区  ›  Jon Seigel

如何使用nhibernate标准来转义like子句?

  •  4
  • Jon Seigel  · 技术社区  · 15 年前

    在搜索查询的这一部分中,我们使用的代码是直截了当的:

    myCriteria.Add(
        Expression.InsensitiveLike("Code", itemCode, MatchMode.Anywhere));

    这在生产环境中很好。

    问题是,我们的一个客户端的项代码包含此查询需要匹配的%符号。此代码生成的SQL输出类似于:

    SELECT ... FROM ItemCodes WHERE ... AND Code LIKE '%ItemWith%Symbol%'

    这清楚地解释了为什么他们在项目搜索中会得到一些奇怪的结果。

    有没有一种方法可以使用编程 Criteria 方法?


    附录:

    我们使用的是稍微旧一点的nhibernate版本,2.1.0.4000(目前编写时是2.1.2.4853),但我查看了发行说明,没有提到对此进行修复。我在他们的追踪器里也没有发现任何问题。

    我们使用的是sql server,所以我可以很容易地转义代码中的特殊字符(%、、、[和^),但是我们使用nhibernate的目的是使我们的应用程序数据库引擎尽可能独立。

    既不 Restrictions.InsensitiveLike() 也不 HqlQueryUtil.GetLikeExpr() 退出它们的输入,并移除 MatchMode 参数对于转义来说没有区别。


    更新: 我发现 someone else 想做同样的事情(三年前),决议是 escapeChar 重载到上面提到的方法(在版本2.0.0.3347中已“修复”)。我在那个问题上加了一条评论,要求进一步解决。

    2 回复  |  直到 15 年前
        1
  •  4
  •   Community CDub    8 年前

    实现数据库独立性的唯一方法是对搜索字符串中的每个字符进行转义,并调用likeexpression上的适当构造函数,如我前面的回答所示。您可以手动执行此操作,也可以扩展likeexpression:

        public class LikeExpressionEscaped : LikeExpression
        {
            private static string EscapeValue(string value)
            {
                var chars = value.ToCharArray();
                var strs = chars.Select(x => x.ToString()).ToArray();
                return "\\" + string.Join("\\", strs);
            }
    
            public LikeExpressionEscaped(string propertyName, string value, MatchMode matchMode, bool ignoreCase)
                : base(propertyName, EscapeValue(value), matchMode, '\\', ignoreCase)
            {}
        }
    

    毫无疑问,有一种更有效的方法来创建转义字符串(请参阅 this question )。用途是:

    var exp = new LikeExpressionEscaped("Code", itemCode, MatchMode.Anywhere, true);
    myCriteria.Add(exp);
    
        2
  •  2
  •   Jamie Ide    15 年前

    您可以创建likeexpression的实例来实现这一点。在本例中,我用反斜杠(必须对反斜杠本身进行转义)转义%

    var itemCode = "ItemWith%Symbol";
    itemCode = searchCode.Replace("%", "\\%");
    var exp = new LikeExpression("Code", itemCode, MatchMode.Anywhere, '\\', true);
    myCriteria.Add(exp);
    

    我没有看到使用此重载返回LikeExpression的静态方法。

    顺便说一下,如果您使用的是sql server,那么默认情况下它是不区分大小写的。

    推荐文章