As usual in NHibernate, the answer is : yes, you can!!
The LINQ extension
As example I’m going to use an extension of string to mimic the SQL LIKE clause.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);
}
}
{
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 integration
The integration point is a class implementing : ILinqToHqlGeneratorsRegistryThe LinqToHqlGeneratorsRegistry provides the way to recognize and translate methods and properties of varios classes. Our DefaultLinqToHqlGeneratorsRegistry can manage LINQ extensions as Any, All, Min, Max etc., methods as StratsWith, EndsWith, Contains, IndexOf etc. or properties as Year, Month, Day, Length etc.
First of all I have to implements a IHqlGeneratorForMethod. NHibernate provides a cooked base class and my implementation will look as:
public class IsLikeGenerator : BaseHqlGeneratorForMethod
{
public IsLikeGenerator()
{
SupportedMethods = new[] {ReflectionHelper.GetMethod(() => 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 IsLikeGenerator()
{
SupportedMethods = new[] {ReflectionHelper.GetMethod(() => 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());
}
}
Having the HQL generator for my extension I can implements my ILinqToHqlGeneratorsRegistry extending the default implementation.
public class MyLinqToHqlGeneratorsRegistry: DefaultLinqToHqlGeneratorsRegistry
{
public MyLinqToHqlGeneratorsRegistry():base()
{
RegisterGenerator(ReflectionHelper.GetMethod(() => MyLinqExtensions.IsLike(null, null)),
new IsLikeGenerator());
}
}
{
public MyLinqToHqlGeneratorsRegistry():base()
{
RegisterGenerator(ReflectionHelper.GetMethod(() => MyLinqExtensions.IsLike(null, null)),
new IsLikeGenerator());
}
}
The configuration
The last step to use my IsLike extension to query the DB is the configuration of my LinqToHQLGeneratorsRegistry.The name of the property for the XML configuration is : linqtohql.generatorsregistry
In NHibernate 3 you can use the Loquacious-configuration :
configuration.LinqToHqlGeneratorsRegistry<MyLinqToHqlGeneratorsRegistry>();
And now...
var contacts = (from c in db.Customers where c.ContactName.IsLike("%Thomas%") select c).ToList();
Welcome to NHibernate3!!!