0

我正在尝试将 NHibernate 与 sql server 功能进行高级使用。
我正在使用 NHibernate 的 ICriteria 接口为我的列表视图提供分页、排序和过滤。其中一个业务对象是来自 3 个不同表的项目的聚合。为了在数据库中进行这种聚合,我使用了一个 transact-sql 函数,接受参数。
我正在使用 session.GetNamedQuery 返回的 IQuery 接口来调用该函数。但为了使用分页/过滤/排序代码,我想使用 ICriteria 接口。为了实现这一点,我考虑过:

  1. 开启新交易
  2. 调用将创建一个全局临时表的函数(而不是像现在这样返回结果)
  3. 以某种方式改变 NHibernate 映射,使其适用于临时表(不确定我能做到这一点,这也必须特定于我创建事务的范围......)
  4. 使用 ICriteria 接口使用新映射在新表上运行查询
  5. 删除临时表

所以有几个问题:

  1. 你能建议一个替代方案吗?
  2. 是否可以在运行时在本地为特定代码范围替换 NHibernate 映射中的表?
  3. 生成和处理临时表的成本是多少?
4

3 回答 3

1

你能用视图替换函数吗?此视图可以聚合 3 个表,由 NHibernate 映射,并轻松分页/排序/过滤。

于 2010-01-18T16:11:04.087 回答
1

我写了一篇博文,展示了如何在这里做到这一点:使用 nhibernate 和 sql server 临时表进行性能密集型查询的分页

于 2011-02-11T16:48:29.900 回答
0

我使用 SQL 2012 Dialect 在 Hibernate SQL 查询中使用表变量,如下所示。 对于我的场景,无论我如何构建过滤器,我都无法在 17 秒内完成特定的参数化、分页查询。通过使用表变量,抓取页面大小为 1000 的页面 N 的时间导致亚秒级响应。

所有的魔法都发生在下面的 SQL 中

  1. 创建一个表变量-declare @temporderstatus table
  2. 选择表变量中的行-由sqlfilter字符串insert into @temporderstatus中的 sql 过滤
  3. 从表变量中选择数据以返回到 NHibernate排序,以便分页返回可预测的结果集 -select OrderNum, Customer... from @temporderstatus ORDER BY StatusCodeChangedDate, OrderNum
  4. 使用 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;
于 2018-10-11T09:08:16.730 回答