NHibernate3剖析:Query篇之NHibernate.Linq自定义扩展

发布时间:2026/7/5 2:15:07
NHibernate3剖析:Query篇之NHibernate.Linq自定义扩展 Linq provider自定义扩展机制在NHibernate中几乎所有的面向对象查询语言(HQL、Criteria、QueryOver)都是可扩展的Linq也不例外。我们可以扩展自定义LINQ-provider并将LINQ扩展方法转换为SQL。下面看看NHibernate对外提供的Linq provider扩展机制。ILinqToHqlGeneratorsRegistry接口为Hql-Generators提供统一注册接口在Build SessionFactory的时候NHibernate注册提供的Hql-Generators。LinqToHqlGeneratorsRegistryFactory注册工厂提供Hql-Generators注册工厂默认注册NHibernate内置支持的NHibernate.Linq查询譬如DateTime类型提供的属性和方法、String类型提供的属性和方法、Queryable和Enumerable提供的方法。可以通过Configuration的linqtohql.generatorsregistry配置节或者Configuration类提供的LinqToHqlGeneratorsRegistry扩展方法注册实现ILinqToHqlGeneratorsRegistry接口自定义Linq provider扩展。DefaultLinqToHqlGeneratorsRegistry注册类默认NHibernate内置支持的NHibernate.Linq查询注册类继承ILinqToHqlGeneratorsRegistry接口。三种Hql-Generators接口IRuntimeMethodHqlGenerator对运行时方法注册ICollectionT集合的Contains方法带LinqExtensionMethodAttribute的扩展方法。IHqlGeneratorForMethod对方法Hql生成譬如Queryable和Enumerable类的Any、All、Min、Max、Contains方法string类型的StartsWith、EndsWith、Contains、Equals、ToLower、ToLowerInvariant、ToUpper、ToUpperInvariant、Substring、IndexOf、Replace方法和带LinqExtensionMethodAttribute的扩展方法NHibernate内部用于识别和转换Visitors类的方法。IHqlGeneratorForProperty对属性Hql生成譬如DateTime类型的Year、Month、Day、Hour、Minute、Second、Date属性string类型的Length属性。NHibernate内部用于识别和转换Visitors类的属性。两种Hql-Generators抽象类BaseHqlGeneratorForMethod​编辑BaseHqlGeneratorForMethod抽象类实现IHqlGeneratorForMethod接口。用于定义方法的Hql-Generators。例如NHibernate内置提供string类型StartWith()方法的Hql-Generators实现​编辑BaseHqlGeneratorForProperty​编辑BaseHqlGeneratorForProperty抽象类实现IHqlGeneratorForProperty接口。用于定义属性的Hql-Generators。例如NHibernate内置提供string类型Length属性的Hql-Generators实现​编辑知道了上面的内容相信你可以自定义一个Linq provider扩展了。Linq provider自定义扩展实现我们以String类型为例使用IsLike扩展方法对String类型扩展模仿SQL中的LIKE从句。1.Linq扩展方法使用IsLike扩展方法对String类型扩展代码如下//Code Snippets Copyright http://lyj.cnblogs.com/ 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); } }2.IsLike扩展方法的Hql-Generators实现创建完扩展方法之后就可以在内存中使用这个扩展了。但是我们需要NHibernate把他翻译成持久化查询(persistence-queries)即需要转换为SQL。像NHibernate内置的实现类似我们需要创建一个Generators//Code Snippets Copyright http://lyj.cnblogs.com/ public class IsLikeGenerator : BaseHqlGeneratorForMethod { public IsLikeGenerator() { SupportedMethods new[] {ReflectionHelper.GetMethodDefinition(() MyLinqExtensions.IsLike(null, null))}; } public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollectionExpression arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor) { return treeBuilder.Like(visitor.Visit(arguments[0]).AsExpression(), visitor.Visit(arguments[1]).AsExpression()); }