Расширение LinqToHql для NHibernate не регистрируется должным образом, получая System.NotSupportedException - PullRequest
2 голосов
/ 22 декабря 2010

Я реализую расширение "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 ]

2 голосов
/ 23 декабря 2010

После выяснения того, что делает 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 () сработало отлично.

0 голосов
/ 22 декабря 2010

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

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

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

...