Как мне избежать оговорки LIKE? - PullRequest
4 голосов
/ 22 марта 2010

Код, который мы используем, прост в этой части поискового запроса:

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 не имеет значения в том, что касается экранирования.


Я нашел кого-то другого , желающего сделать то же самое (три года назад), и было решено добавить перегрузки escapeChar к методам, которые я упоминал выше (это было "исправлено" в версии 2.0.0.3347). Я добавил комментарий к этой проблеме с просьбой о дальнейшем разрешении.

Ответы [ 2 ]

4 голосов
/ 23 марта 2010

Единственный способ найти независимость от базы данных - это экранировать каждый символ в строке поиска и вызывать соответствующий конструктор 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)
        {}
    }

Нет сомнений в более эффективном способе создания экранированной строки (см. Ответы и комментарии к этому вопросу ). Использование:

var exp = new LikeExpressionEscaped("Code", itemCode, MatchMode.Anywhere, true);
myCriteria.Add(exp);
2 голосов
/ 22 марта 2010

Вы можете создать экземпляр LikeExpression, чтобы выполнить это. В этом примере я экранирую% обратной косой чертой (которая сама должна быть экранирована):

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

Я не видел статического метода для возврата выражения LikeExpression с использованием этой перегрузки.

Кстати, если вы используете SQL Server, он по умолчанию не учитывает регистр.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...