一起谈.NET技术,NHibernate3.0剖析:Query篇之NHibernate.Linq自定义扩展

简介:   系列引入  NHibernate3.0剖析系列分别从Configuration篇、Mapping篇、Query篇、Session策略篇、应用篇等方面全面揭示NHibernate3.0新特性和应用及其各种应用程序的集成,基于NHibernte3.0版本。

  系列引入

  NHibernate3.0剖析系列分别从Configuration篇、Mapping篇、Query篇、Session策略篇、应用篇等方面全面揭示NHibernate3.0新特性和应用及其各种应用程序的集成,基于NHibernte3.0版本。如果你还不熟悉NHibernate,可以快速阅读NHibernate之旅系列文章导航系列入门,如果你已经在用NHibernate了,那么请跟上NHibernate3.0剖析系列吧。

  概述

  NHibernate.Linq除了本身提供了标准查询运算符和NHibernate特有的两个强查询立即抓取(EagerFetching)和查询缓存(QueryCacheable),我们也可以自己定义Linq provider扩展。

  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

  对运行时方法注册,ICollection<T>集合的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

Linq-BaseHqlGeneratorForMethod

  BaseHqlGeneratorForMethod抽象类实现IHqlGeneratorForMethod接口。用于定义方法的Hql-Generators。例如NHibernate内置提供string类型StartWith()方法的Hql-Generators实现:

Linq-StartsWithGenerator  BaseHqlGeneratorForProperty

Linq-BaseHqlGeneratorForProperty  BaseHqlGeneratorForProperty抽象类实现IHqlGeneratorForProperty接口。用于定义属性的Hql-Generators。例如NHibernate内置提供string类型Length属性的Hql-Generators实现:

Linq-LengthGenerator  知道了上面的内容,相信你可以自定义一个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,
ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
return treeBuilder.Like(visitor.Visit(arguments[0]).AsExpression(),
visitor.Visit(arguments[1]).AsExpression());
}
}

  3.注册IsLike扩展方法Hql-Generators

  我们继承默认NHibernate内置支持的NHibernate.Linq查询注册类,这样可以把我们自定义的Hql-Generators附加进去。

//Code Snippets Copyright http://lyj.cnblogs.com/
public class MyLinqToHqlGeneratorsRegistry: DefaultLinqToHqlGeneratorsRegistry
{
public MyLinqToHqlGeneratorsRegistry()
{
RegisterGenerator(ReflectionHelper.GetMethodDefinition(
() => MyLinqExtensions.IsLike(null, null)),new IsLikeGenerator());
}
}

  4.配置自定义Linq provider扩展

  使用IsLike扩展方法去查询DB数据,我们需要配置我们自定义的LinqToHQLGeneratorsRegistry,如果使用配置文件配置,则需要使用linqtohql.generatorsregistry:

  如果使用Loquacious-configuration就是这样:

//Code Snippets Copyright http://lyj.cnblogs.com/
configuration.LinqToHqlGeneratorsRegistry<MyLinqToHqlGeneratorsRegistry>();

  5.使用IsLike扩展方法

//Code Snippets Copyright http://lyj.cnblogs.com/
var users = session.Query<User>().Where(o => o.Name.IsLike("%永京%")).ToList();

  6.执行结果

Linq-IsLikeExtensions  结语

  通过这篇文章学习了Linq provider自定义扩展机制和实现。

  参考资料

  Fabio Maulo:NHibernate LINQ provider extension

  NHibernate Jira: Add support for user-provided extensions to the Linq provider

  希望本文对你有所帮助。

目录
相关文章
|
7天前
|
监控 安全 API
Docker + .NET API:简化部署和扩展
Docker + .NET API:简化部署和扩展
16 0
|
29天前
|
人工智能 前端开发 开发工具
解读.NET 技术的开发潜力
本文全面介绍了.NET技术在软件开发领域的核心优势、创新应用及面临的挑战。.NET以其统一的开发平台、强大的工具和跨平台能力,成为企业级应用、Web应用乃至游戏开发的理想选择。然而,在性能优化、容器化及AI集成等方面仍需不断突破。通过积极拥抱开源和社区驱动模式,.NET将持续推动软件开发的进步。
47 1
|
8天前
|
监控 安全 API
最完美的扩展Docker + .NET API:简化部署和扩展
最完美的扩展Docker + .NET API:简化部署和扩展
28 0
|
1月前
|
监控 网络协议 API
.NET WebSocket 技术深入解析,你学会了吗?
【9月更文挑战第4天】WebSocket 作为一种全双工协议,凭借低延迟和高性能特点,成为实时应用的首选技术。.NET 框架提供了强大的 WebSocket 支持,使实时通信变得简单。本文介绍 WebSocket 的基本概念、.NET 中的使用方法及编程模型,并探讨其在实时聊天、监控、在线游戏和协同编辑等场景的应用,同时分享最佳实践,帮助开发者构建高效实时应用。
93 12
|
1月前
|
人工智能 前端开发 Devops
.NET技术自发布以来,在软件开发领域发挥了重要作用
【9月更文挑战第12天】.NET技术自发布以来,在软件开发领域发挥了重要作用。本文分为三部分探讨其在现代开发中的应用:首先介绍.NET的核心价值,包括语言多样性、强大的开发工具支持、丰富的类库、跨平台能力和活跃的社区;接着分析其在企业级应用、Web开发、移动应用、云服务及游戏开发中的实际应用;最后讨论.NET面临的挑战与未来趋势,如性能优化、容器化、AI集成及跨平台框架竞争等。通过不断的技术创新和社区驱动,.NET将持续推动软件开发的进步。
32 4
|
1月前
|
人工智能 开发框架 算法
C#/.NET/.NET Core技术前沿周刊 | 第 2 期(2024年8.19-8.25)
C#/.NET/.NET Core技术前沿周刊 | 第 2 期(2024年8.19-8.25)
|
1月前
|
传感器 应用服务中间件 Linux
C#/.NET/.NET Core技术前沿周刊 | 第 3 期(2024年8.26-8.31)
C#/.NET/.NET Core技术前沿周刊 | 第 3 期(2024年8.26-8.31)
|
1月前
|
人工智能 算法 C#
C#/.NET/.NET Core技术前沿周刊 | 第 1 期(2024年8.12-8.18)
C#/.NET/.NET Core技术前沿周刊 | 第 1 期(2024年8.12-8.18)
|
1月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
32 7
|
1月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
42 0