5

I have a nhibernate linq query that looks like this:

 from b in session.Query<Bookmark>()
where b.Uri.Equals(uri) ||
      b.Uri.Equals("www." + uri) ||
string.Concat("www.", b.Uri).Equals(uri)
select b

This blows up, saying Concat isn't support, but when I change it to

 from b in session.Query<Bookmark>()
where b.Uri.Equals(uri) ||
      b.Uri.Equals("www." + uri) ||
      ("www." + b.Uri).Equals(uri)
select b

It runs fine, but the query looks like this:

select cast(count(*) as SIGNED) as col_0_0_ 
 from bookmarks bookmark0_ 
 where bookmark0_.Uri = 'www.google.com' 
    or bookmark0_.Uri = 'www.www.google.com'
    or 'www.'+bookmark0_.Uri = 'www.google.com';

Where the 'www.'+bookmark0_.Uri is "added" instead of concat('www.',bookmark0_.Uri). Is there a way to concatenate strings in Linq for NHibernate for MySQL?

1
  • see correct answer here, but they're using criteria api Commented May 24, 2011 at 7:01

2 Answers 2

6

The following is an HqlGenerator that solves this problem:

public class ConcatHqlGenerator : BaseHqlGeneratorForMethod
{
    public ConcatHqlGenerator()
        : base()
    {
        this.SupportedMethods = new[] 
        { ReflectionHelper.GetMethodDefinition(() => string.Concat(null, null)) };
    }

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

Add this to your HQLGeneratorsRegistry and you will be good to go with calls to string.Concat in you LINQ statements.

public class LinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public LinqToHqlGeneratorsRegistry()
        : base()
    {
        this.Merge(new ConcatHqlGenerator());
    }
}
private static ISessionFactory CreateSessionFactory()
{
    var configuration = new NHib.Cfg.Configuration();
    configuration.Properties.Add(NHibernate.Cfg
                                           .Environment.LinqToHqlGeneratorsRegistry, 
typeof(LinqToHqlGeneratorsRegistry).AssemblyQualifiedName);
    configuration.Configure();
    return configuration.BuildSessionFactory();
}
Sign up to request clarification or add additional context in comments.

3 Comments

This solution got the query from b in session.Query<Bookmark>() where b.Uri.Equals(uri) || b.Uri.Equals("www." + uri) || string.Concat("www.", b.Uri).Equals(uri) select b; to work, Thanks Travis!
If you are using something other than string this will work: treeBuilder.Cast(visitor.Visit(arguments[0]).AsExpression(),typeof(string))
Or better yet: arguments[0].Type==typeof(string)? visitor.Visit(arguments[0]).AsExpression(): treeBuilder.Cast(visitor.Visit(arguments[0]).AsExpression(),typeof(string))
0

thats Because concatination of two types. May be you can try string.Concat("www" + b.Uri.ToString);

3 Comments

it appears that nhib linq knows nothing about function String.Concat, but it's expandable so you can implement Concat for linq to understand it
jjjjj, have you got a sample of how to write a linq overload function?
dipti-mehta, they are both of type string and in the database, uri is a varchar... The issue is with how mysql handles string concatenation, unlike SQL server, you must use the concat function which NHibernate doesn't seem to recognise in it's attempt at linq... Yet

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.