如何逃避LIKE条款?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何逃避LIKE条款?相关的知识,希望对你有一定的参考价值。

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

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),但是我检查了发行说明,并没有提到修复此问题。我也没有在他们的bugtracker中找到任何未解决的问题。

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

Restrictions.InsensitiveLike()HqlQueryUtil.GetLikeExpr()都没有逃脱他们的输入,并且删除MatchMode参数对于逃避没有任何区别。


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

答案

我能找到实现数据库独立性的唯一方法是转义搜索字符串中的每个字符,并在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);
另一答案

您可以创建LikeExpression的实例来完成此任务。在这个例子中,我使用反斜杠(它本身必须被转义)转义%:

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

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

顺便说一下,如果您使用的是SQL Server,则默认情况下不区分大小写。

以上是关于如何逃避LIKE条款?的主要内容,如果未能解决你的问题,请参考以下文章

Vscode在使用变量之前转义斜杠

SQLite的LIKE语句实现字符片段筛选的功能

SQLite的LIKE语句实现字符片段筛选的功能

SQLite的LIKE语句实现字符片段筛选的功能

SQLite的LIKE语句实现字符片段筛选的功能

使用 Doctrine 查询构建器正确转义 LIKE 查询