我有一个大型 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已经关闭(并且似乎已经关闭了数周)!OnPrepareStatementEmptyInterceptor
有没有人必须执行这样的任务?是否可以以干净且类型安全的方式解构 NHibernate 查询?是否有完全不同的方法可以实现相同的目标(考虑到无法更改数据库/服务器排序规则的相同约束)?