我使用 SQL 2012 Dialect 在 Hibernate SQL 查询中使用表变量,如下所示。
对于我的场景,无论我如何构建过滤器,我都无法在 17 秒内完成特定的参数化、分页查询。通过使用表变量,抓取页面大小为 1000 的页面 N 的时间导致亚秒级响应。
所有的魔法都发生在下面的 SQL 中
- 创建一个表变量-
declare @temporderstatus table
- 选择表变量中的行-由sqlfilter字符串
insert into @temporderstatus
中的 sql 过滤
- 从表变量中选择数据以返回到 NHibernate排序,以便分页返回可预测的结果集 -
select OrderNum, Customer... from @temporderstatus ORDER BY StatusCodeChangedDate, OrderNum
- 使用 NHibernate 分页函数使用 SQL Server 2012 方言插入必要的ROW/OFFSET语句 -
SetFirstResult((pagination.Page - 1) * pagination.PageSize).SetMaxResults( pagination.PageSize )
与临时表不同,表变量会自行清理,因此它非常适合 NHibernate 场景,其中您有一个正在服务分页请求的 Web 服务器。
这是我的代码...
var session = _sessionManager.GetStatelessSession();
StringBuilder sqlfilter = new StringBuilder(
@"FROM Orders o join OrderType ot ON o.OrderType = ot.OrderType where o.StatusDate between :fromDate and :toDate" );
var mainQuery = session.CreateSQLQuery(
$@"declare @temporderstatus table (OrderNum int not null, CustomerID int, OrderType varchar(16), Status varchar(3), StatusCodeChangedDate datetime, OrderDate datetime, DeliveryDate datetime)
insert into @temporderstatus
SELECT o.OrderNum, o.CustomerID, ot.Description AS OrderType, o.StatusCode AS Status, o.StatusCodeChangedDate, o.OrderDate, o.DeliveryDate
{sqlfilter}
select OrderNum, CustomerID, OrderType, Status, StatusCodeChangedDate, OrderDate, DeliveryDate
from @temporderstatus
ORDER BY StatusCodeChangedDate, OrderNum
");
//construct the count query
var totalCountQuery = session.CreateSQLQuery($"SELECT COUNT(1) OCount {sqlfilter} ");
totalCountQuery.AddScalar("OCount", NHibernateUtil.Int32);
totalCountQuery.SetParameter("fromDate", criteria.fromDate);
totalCountQuery.SetParameter("toDate", criteria.toDate);
var totalCountResults = totalCountQuery.UniqueResult<int>();
pagination.TotalResultCount = totalCountResults;
if (pagination.TotalResultCount == 0)
{
//no results so don't waste time doing another query
return new List<OrderDataDto>();
}
//finish constructing the main query
mainQuery.AddEntity(typeof(OrderDataDto));
mainQuery.SetParameter("fromDate", criteria.fromDate);
mainQuery.SetParameter("toDate", criteria.toDate);
var mainQueryResults = mainQuery
.SetFirstResult((pagination.Page - 1)*pagination.PageSize).SetMaxResults(pagination.PageSize);
var results = mainQueryResults.List<OrderDataDto>();
return results;