문제

I'm implementing the "IsLike" extension to LINQ and Nhibernate as outlined in this post by Fabio.

I have the code like so:

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);
    }
}

The extension is registered in the configuration (3rd line):

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

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

But when I try running the query I get an exception

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

It's like the extensions is not registered or not triggering. The property is is set since I tried adding it to the configuration in the test itself and got an exception that the key already existed.

NHibernate assembly version is 3.0.0.4000

Any suggestions to what I might be doing wrong?

도움이 되었습니까?

해결책

After figuring out what Sharp Architecture does and learning a bit more about the SessionFactory (ie that it cannot be changed) the solution was to add the properties to the NHibernateSession.Init call

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

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

I tried adding the property to the config file but got validation errors on the file. Adding it to the .Init() call worked perfectly though.

다른 팁

Since I know Fabio's example works, it has to be something in your wrapper classes, for which we don't have the source.

What does NHibernateSession.Init do?

When are you building your SessionFactory?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top