Расширение LinqToHql для NHibernate не регистрируется должным образом, получая System.NotSupportedException

Я реализую расширение "IsLike" для LINQ и Nhibernate, как описано в этом посте Фабио.

У меня есть код так:

public class MyLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public MyLinqToHqlGeneratorsRegistry()
        : base()
    {
        RegisterGenerator(ReflectionHelper.GetMethodDefinition(() =>
            MyLinqExtensions.IsLike(null, null)),
                          new IsLikeGenerator());
    }
}


public class IsLikeGenerator : BaseHqlGeneratorForMethod
{
    public IsLikeGenerator()
    {
        SupportedMethods = new[] { ReflectionHelper.GetMethodDefinition(() =>
          MyLinqExtensions.IsLike(null, null)) };
    }

    public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject,
        ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
    {
        return treeBuilder.Like(visitor.Visit(arguments[0]).AsExpression(),
                                visitor.Visit(arguments[1]).AsExpression());
    }
}

public static class MyLinqExtensions
{
    public static bool IsLike(this string source, string pattern)
    {
        pattern = Regex.Escape(pattern);
        pattern = pattern.Replace("%", ".*?").Replace("_", ".");
        pattern = pattern.Replace(@"\[", "[").Replace(@"\]", "]").Replace(@"\^", "^");

        return Regex.IsMatch(source, pattern);
    }
}

Расширение зарегистрировано в конфигурации (3-я строка):

    protected void InitializeNHibernateSession()
    {
        NHibernateConfiguration = NHibernateSession.Init(
                               new SimpleSessionStorage(),
                               GetMappingAssemblies(),
                               GetNHibernateConfig());

        NHibernateConfiguration.Properties.Add(
                   Environment.LinqToHqlGeneratorsRegistry, 
                   typeof(MyLinqToHqlGeneratorsRegistry).AssemblyQualifiedName);
        NHibernateSession.RegisterInterceptor(new AuditInterceptor());
    }

Но когда я пытаюсь выполнить запрос, я получаю исключение

System.NotSupportedException was unhandled by user code
  Message=Boolean IsLike(System.String, System.String)
  Source=NHibernate
  StackTrace:
       at     NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitMethodCallExpression    (MethodCallExpression expression)
       at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression    (Expression     expression)
       at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.Visit(Expression expression, VisitorParameters parameters)
       at NHibernate.Linq.Visitors.QueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
       at Remotion.Data.Linq.Clauses.WhereClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel, Int32 index)
       at Remotion.Data.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection`1 bodyClauses, QueryModel queryModel)
       at Remotion.Data.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel     queryModel)
       at NHibernate.Linq.Visitors.QueryModelVisitor.Visit()
       at NHibernate.Linq.Visitors.QueryModelVisitor.GenerateHqlQuery(QueryModel queryModel, VisitorParameters parameters, Boolean root)
       at NHibernate.Linq.NhLinqExpression.Translate(ISessionFactoryImplementor sessionFactory)
       at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(String queryIdentifier, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)
       at NHibernate.Engine.Query.HQLExpressionQueryPlan.CreateTranslators(String expressionStr, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)
       at NHibernate.Engine.Query.HQLExpressionQueryPlan..ctor(String expressionStr, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)
       at NHibernate.Engine.Query.HQLExpressionQueryPlan..ctor(String expressionStr, IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)
       at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters)
       at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow)
       at NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression)
       at NHibernate.Linq.NhQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery)
       at NHibernate.Linq.NhQueryProvider.Execute(Expression expression)
       at NHibernate.Linq.NhQueryProvider.Execute[TResult](Expression expression)
       at System.Linq.Queryable.Count[TSource](IQueryable`1 source)
       at MyProject.Data.Specification.LinqSpecRepository`1.FindAllPaged(Specification`1 specification, Int32 currentPage, Int32 noOfItemsPerPage) in c:\source\MyProject\Specification\LinqSpecRepository.cs:line 47
       at MyProject.Tests.PersonRepositoryTests_UserSearch.FilteredQuery_CanPerformWildCardAtTheEndSearch() in c:\source\MyProject.Tests\PersonRepositoryTests_UserSearch.cs:line 51

Это как расширения не зарегистрированы или не запускаются. Это свойство установлено, поскольку я попытался добавить его в конфигурацию в самом тесте и получил исключение, что ключ уже существует.

Сборка NHibernate версия 3.0.0.4000

Любые предложения о том, что я могу делать не так?

2 ответа

Решение

После выяснения того, что делает Sharp Architecture, и более подробного изучения SessionFactory (то есть того, что его нельзя изменить) было решено добавить свойства в вызов NHibernateSession.Init.

var configProperties = new Dictionary<string, string> {{
   Environment.LinqToHqlGeneratorsRegistry,
   typeof (MyLinqToHqlGeneratorsRegistry).AssemblyQualifiedName
}};

NHibernateConfiguration = NHibernateSession.Init(
                            new SimpleSessionStorage(),
                            GetMappingAssemblies(), null,
                            GetNHibernateConfig(), configProperties, null);

Я попытался добавить свойство в файл конфигурации, но получил ошибки проверки файла. Хотя добавление его к вызову.Init() работает отлично.

Поскольку я знаю, что пример Фабио работает, он должен быть чем-то в ваших классах-оболочках, для которых у нас нет исходного кода.

Что делает NHibernateSession.Init?

Когда вы строите свой SessionFactory?

Другие вопросы по тегам