используя временную таблицу с NHibernate

Я пытаюсь сделать то, что кажется расширенным использованием NHibernate с функциями сервера sql.
Я использую интерфейс ICriteria NHibernate для разбивки по страницам, сортировки и фильтрации моих списков. один из бизнес-объектов - это совокупность элементов из 3-х разных таблиц. для того, чтобы выполнить эту агрегацию в БД, я использовал функцию transact-sql, принимающую параметры.
Я использую интерфейс IQuery, возвращаемый session.GetNamedQuery для вызова функции. но чтобы использовать код подкачки / фильтрации / сортировки, я хотел бы использовать интерфейс ICriteria. чтобы добиться этого, я подумал:

  1. Открытие новой транзакции
  2. вызов функции, которая создаст глобальную временную таблицу (вместо возврата результата, как сейчас)
  3. каким-то образом изменить отображение NHibernate, чтобы оно применялось для временной таблицы (не уверен, что я могу это сделать, также это должно быть специфичным для области, в которой я создаю транзакцию ...)
  4. запустите запрос в новой таблице, используя новое сопоставление, используя интерфейс ICriteria
  5. Удалить временную таблицу

Итак, ряд вопросов:

  1. вы можете предложить альтернативу?
  2. Можно ли заменить таблицу в отображении NHibernate во время выполнения локально для определенной области кода?
  3. насколько дорого обойдется создание и удаление временной таблицы?

person Yonatan Karni    schedule 17.01.2010    source источник
comment
Я не могу предложить альтернативу, если не знаю, где предложить альтернативу. Какие классы, какие таблицы? Звучит странно использовать временную таблицу для того, что вы описываете, но, может быть, это логично в контексте, в котором вы ее используете?   -  person Paco    schedule 17.01.2010
comment
Я согласен с Пако, я не вижу необходимости в временном столе ..   -  person Mauricio Scheffer    schedule 17.01.2010


Ответы (3)


Можете ли вы заменить функцию видом? Это представление может объединять 3 таблицы, отображать их с помощью NHibernate и легко выгружать / сортировать / фильтровать.

person dotjoe    schedule 18.01.2010
comment
Я мог бы это сделать, но это снизило бы производительность, поскольку соединение будет выполнено для всех строк в трех таблицах, в отличие от соединения, которое я использую в функции, которая выполняется для определенного внешнего ключа. Я надеюсь скоро предоставить дополнительную информацию, как это было предложено @Paco, извините за задержку ... спасибо! - person Yonatan Karni; 19.01.2010

Я написал сообщение в блоге, в котором показано, как именно это можно сделать здесь: разбиение на страницы для запросов с высокой производительностью с использованием временных таблиц nhibernate и sql server

person Khaja Minhajuddin    schedule 11.02.2011

Я использую табличную переменную внутри запроса SQL Hibernate с использованием диалекта SQL 2012, как показано ниже. В моем сценарии я не мог заставить конкретный параметризованный запрос с разбивкой на страницы работать менее чем за 17 секунд, как бы я ни построил фильтр. При использовании табличной переменной время захвата страницы N с размером страницы 1000 привело к ответу менее секунды.

Вся магия происходит в SQL ниже,

  1. создает табличную переменную - declare @temporderstatus table
  2. выбирает строки в табличной переменной - insert into @temporderstatus фильтруется по sql в строке sqlfilter
  3. выбирает данные из переменной таблицы для возврата в NHibernate, упорядоченный таким образом, чтобы разбивка на страницы возвращала предсказуемый набор результатов - select OrderNum, Customer... from @temporderstatus ORDER BY StatusCodeChangedDate, OrderNum
  4. использует функции разбиения по страницам NHibernate для вставки необходимых операторов ROW / OFFSET с использованием диалекта SQL Server 2012 - SetFirstResult((pagination.Page - 1) * pagination.PageSize).SetMaxResults( pagination.PageSize )

В отличие от временной таблицы, табличная переменная очищается после себя, поэтому она идеально подходит для сценариев NHibernate, где у вас есть веб-сервер, обслуживающий запросы с разбивкой на страницы.

Вот мой код ...

            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;
person neoscribe    schedule 11.10.2018