1
votes

I have created the following NHibernate HQL generator:

public class ContainsGenerator : BaseHqlGeneratorForMethod {
    public ContainsGenerator() {
        SupportedMethods = new[] {
            ReflectionHelper.GetMethodDefinition(() =>
                MyExtensions.Contains(null, null))
        };
    }

    public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject,
        ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder,
        IHqlExpressionVisitor visitor) {
        var exp = FormatExpression((string)((ConstantExpression)arguments[1]).Value);

        return treeBuilder.BooleanMethodCall("CONTAINS", new[] {
            visitor.Visit(arguments[0]).AsExpression(),
            treeBuilder.Constant(exp)
        });
    }

    private string FormatExpression(string exp) {
        exp = exp.Replace("'", "''");
        exp = exp.Replace("\"", "");
        exp = (char)34 + Regex.Replace(exp,
           "(AND NOT|AND|OR NOT|OR) ",
           (char)34 + " $1 " + (char)34, RegexOptions.IgnoreCase)
           + (char)34;

        return exp;
    }
}

This is used to do Full-Text searching to speed up searching over large tables.

The only difference to this and previous generators I've built in the past is that I call FormatExpression to convert the search expression to the correct format that SQL Server understands. However this seems to be the problem because although it works the first time I fire the query, subsequent searches produces the same query and the second argument passed into CONTAINS never changes. For example If I say:

var products = session.Query<Product>().Where(p => p.Name.Contains("Test 1")).ToList();

It will produce the following query:

select product0_.Id as Id2_, product0_.Name as Name2_, from [dbo].Products product0_ where CONTAINS(product0_.Name, '"Test 1"')

Now if I say:

var products = session.Query<Product>().Where(p => p.Name.Contains("Test 2")).ToList();

It produces exactly the same query.

I'd appreciate it if someone could show me the correct way to do this. Thanks

1
How did you resolve this, I am facing the same issue - Bronumski
@Bronumski: The only way to get this to work is abit hacky. You need to feed the search expression in as a standard argument. Therefore treeBuilder.Constant(exp) becomes visitor.Visit(arguments[1]).AsExpression(). I then expose the FormatExpression method as a static helper. Finally when you call the it you would then say session.Query<Product>().Where(p => p.Name.Contains(ContainsGenerator.FormatExpression("XXX")).ToList(); - nfplee

1 Answers