Я использую NHibernate 2.1.2.4000GA. Я пытаюсь использовать функцию SQL Server CONTAINS
из HQL и API критериев. Это отлично работает в HQL:Использование CONTAINS из API HQL/Criteria
Однако мне нужно квалифицировать таблицу, о которой идет речь. Это отлично работает:
CONTAINS(table.Column, :value)
Однако мне нужно искать по всем индексированным столбцам в таблице. Я попытался это:
CONTAINS(table.*, :value)
Но я получаю:
NHibernate.Hql.Ast.ANTLR.QuerySyntaxException : Exception of type 'Antlr.Runtime.MissingTokenException' was thrown. near line ... [select table.Id from Entities.Table table where CONTAINS(table.*,:p0) order by table.Id asc]
at NHibernate.Hql.Ast.ANTLR.ErrorCounter.ThrowQueryException()
at NHibernate.Hql.Ast.ANTLR.HqlParseEngine.Parse()
at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.Parse(Boolean isFilter)
at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.DoCompile(IDictionary`2 replacements, Boolean shallow, String collectionRole)
at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.Compile(IDictionary`2 replacements, Boolean shallow)
at NHibernate.Engine.Query.HQLQueryPlan..ctor(String hql, String collectionRole, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)
at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(String queryString, Boolean shallow, IDictionary`2 enabledFilters)
at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(String query, Boolean shallow)
at NHibernate.Impl.AbstractSessionImpl.CreateQuery(String queryString)
Так что, казалось бы, анализатор HQL дроссели на звездочку. Я думал об этом:
CONTAINS(table.Column1, :value) or CONTAINS(table.Column2, :value)
Это не только неэффективно, но и может дает неправильные результаты в зависимости от полного текста предиката в :value
.
Я пробовал настроить свой диалект в соответствии с these instructions, но это не помогает, потому что у вас все еще остается та же проблема: указание table.*
заставляет парсер HQL упасть.
Я думал задания замены запроса:
<property name="query.substitutions">TABLECONTAINS(=CONTAINS(table.*,</property>
А потом просто делать:
TABLECONTAINS(:value)
Но это не работает. Я не уверен, почему - судя по полученной ошибке, замена просто не выполняется, потому что в запросе все еще присутствует TABLECONTAINS. . Кроме того, это не будет работать во всех случаях, потому что я должен был бы знать псевдоним таблицы и динамически подменять его в
Поэтому я выкинула подход перехвата на основе:
using System;
using NHibernate;
using NHibernate.SqlCommand;
public class ContainsInterceptor : EmptyInterceptor
{
public override SqlString OnPrepareStatement(SqlString sql)
{
var indexOfTableContains = sql.IndexOfCaseInsensitive("TABLECONTAINS(");
if (indexOfTableContains != -1)
{
var sqlPart = sql.ToString();
var aliasIndex = sqlPart.LastIndexOf("Table ", indexOfTableContains, StringComparison.Ordinal);
if (aliasIndex == -1)
{
return sql;
}
aliasIndex += "Table ".Length;
var alias = sqlPart.Substring(aliasIndex, sqlPart.IndexOf(" ", aliasIndex, StringComparison.Ordinal) - aliasIndex);
sql = sql.Replace("TABLECONTAINS(", "CONTAINS(" + alias + ".*,");
}
return base.OnPrepareStatement(sql);
}
}
Это работает, и теперь я смогу спать сегодня вечером, но я испытываю внезапное желание посещать предстоящую папскую процессию в Лондоне и выкрикивать признание.
Может ли кто-нибудь предложить лучший способ достичь этого?
Спасибо, но, к сожалению, это не помогает (пробовал это тоже, но забыл поставить на мой вопрос). В принципе, у вас по-прежнему остается та же проблема. Если я хочу указать все столбцы в таблице, мне нужно написать 'contains (table. *,: Term)', но парсер HQL задыхается от этого. Обновление моего вопроса ... –
Возможно, это помогло бы, если бы вы зарегистрировали функцию, включающую имя tablename и свойство. *.Очевидно, вам понадобится отдельная регистрация для каждой таблицы, но это должно (теоретически) по-прежнему сокращать повторение совсем немного ... – DanP
Хммм ... также заметил, что hibernate поддерживает escape-последовательности для hql (пример: http : //www.coderanch.com/t/441409/ORM/java/Special-characters-hql) - не уверен, что NHib разрешает это, хотя ... – DanP