我有一个大型 ASP.NET 应用程序,它使用 NHibernate (v3.2.0.4000) 来访问 SQL Server 2005 作为后端数据存储。我们有多个客户,每个客户都有自己的数据库,但所有数据库都运行在同一台服务器上。
快速的问题:
如果没有在数据库服务器上设置 COLLATION,或者单独的数据库本身,或者重写现有的单独的 NHibernate 查询代码,我如何在 NHibernate 查询中添加自定义 COLLATION 语句,纯粹为了排序目的,在它们到达数据库之前?
更长的问题:
由于有一些新的国际客户,我们需要支持自定义排序规则,以便在我们的应用程序中进行排序。我们不能在数据库(或服务器)级别上执行此操作,因为我们在同一服务器上为每个客户托管一个单独的数据库(每个客户可能有不同的排序要求),并且存在诸如 TempDB 之类的复杂性和多个不同的同一服务器上的排序规则(请参见此处和此处)。
由于 NHibernate 在整个代码库中的使用方式存在差异(即 HQL、ICriteria、普通 SQL、QueryOver 和 Linq 的组合),并且由于其中许多查询非常复杂和混乱,我们希望完全避免更改任何现有的 NHibernate 查询代码。
SQL Server 将允许调用在查询运行时应用特定排序规则的查询,如下所示: SELECT * FROM Customer ORDER BY Surname COLLATE Latin1_General_CI_AS
我也知道 NHibernate 允许创建一个Interceptor
可以在全局或特定于会话的基础上添加到 NHibernate 的(如此处所示),允许在 SQL 语句发送到 SQL Server 之前拦截它。
看来我可以编写一个拦截器类来拦截 SQL 语句,但是,它只允许我捕获原始 SQL 语句(包含 NHibernate 奇怪而美妙的字段和别名)。我不知道是否有任何方法可以干净地解析查询的特定部分(我只需要 ORDER BY 子句)并在检查字段后更改 ORDER BY 子句的各个组成部分(即各个字段)是基于文本的,并允许将 COLLATE 语句附加到它们。
NHibernate 公开了一个NHibernate.SqlCommand.ISqlStringVisitor
听起来很有希望的接口,并且似乎可以对类的方法中SqlString
捕获的内容进行操作,该方法可以被覆盖,但是,我对 NHibernate 的这一部分完全不熟悉,目前它并没有帮助,正如我所写这,NHibernate 所谓的权威信息来源nhibernate.info已经关闭(并且似乎已经关闭了数周)!OnPrepareStatement
EmptyInterceptor
有没有人必须执行这样的任务?是否可以以干净且类型安全的方式解构 NHibernate 查询?是否有完全不同的方法可以实现相同的目标(考虑到无法更改数据库/服务器排序规则的相同约束)?