如何转义LIKE子句?

Jon*_*gel 4 .net nhibernate criteria

我们在搜索查询的这一部分中使用的代码非常简单:

myCriteria.Add(
    Expression.InsensitiveLike("Code", itemCode, MatchMode.Anywhere));
Run Code Online (Sandbox Code Playgroud)

这在生产环境中可以正常工作。

问题是我们的一位客户的商品代码包含此查询需要匹配的%符号。此代码产生的SQL输出类似于:

SELECT ... FROM ItemCodes WHERE ... AND Code LIKE '%ItemWith%Symbol%'
Run Code Online (Sandbox Code Playgroud)

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

有没有一种方法可以使用程序化Criteria方法进行转义?


附录:

我们使用的是NHibernate的稍旧版本2.1.0.4000(撰写本文时的最新版本为2.1.2.4853),但是我检查了发行说明,但没有提及针对此问题的修复程序。我也没有在他们的bugtracker中找到任何未解决的问题。

我们正在使用SQL Server,因此我可以非常轻松地在代码中转义特殊字符(%,_,[和^),但是使用NHibernate的要点是使应用程序尽可能独立于数据库引擎。

无论是Restrictions.InsensitiveLike()HqlQueryUtil.GetLikeExpr()难逃其投入和取出MatchMode参数并没有区别,只要逃避去。


我发现有人(三年前)想做同样的事情,解决方法是将escapeChar重载添加到我上面提到的方法中(在2.0.0.3347版中已“修复”)。我对该问题添加了评论,要求进一步解决。

Jam*_*Ide 5

我能找到的实现数据库独立性的唯一方法是转义搜索字符串中的每个字符,并像我先前的回答一样在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)
        {}
    }
Run Code Online (Sandbox Code Playgroud)

毫无疑问,创建转义字符串的更有效方法(请参阅此问题的答案和注释)。用法是:

var exp = new LikeExpressionEscaped("Code", itemCode, MatchMode.Anywhere, true);
myCriteria.Add(exp);
Run Code Online (Sandbox Code Playgroud)

  • 对于将来的访问者:使用.NET 4,您可以简单地使用`return @“ \” + string.Join(@“ \”,value.ToCharArray())`。更干净,性能更好。 (2认同)