указание стратегии выборки (выбор, объединение и т. д.) в запросе запроса nhibernate - PullRequest
12 голосов
/ 10 марта 2011

Я пытаюсь создать запрос, используя QueryOver , который будет извлекать коллекцию в режиме Выбор или SubSelect .Рассматриваемая сущность Track.Я хочу загрузить коллекцию с именем TrackPrices, и я делаю это в запросе:

q = q.Fetch(item => item.TrackPrices).Eager;

Однако это создает левое соединение , что приводит к проблеме разбиения на страницы,Я хотел бы выполнить отдельный select или subselect .Есть идеи, если это можно сделать?Насколько я знаю, используя API критериев, можно было бы сделать:

q.DetachedCriteria.SetFetchMode("TrackPrices", FetchMode.Select);

Но я хочу избежать магических строк в коде, поэтому я бы предпочел сделать это с помощью API QueryOver.

Ответы [ 3 ]

3 голосов
/ 16 мая 2011

С тех пор, как я опубликовал этот вопрос, мне удалось найти обходной путь / решение, которое также могут оказаться полезными для других.

По сути, в этом случае вы должны сначала создать другой запрос, который четко выделяет первичные ключи основного запроса вместе с разбиением на страницы. Поскольку DISTINCT (ID) будет возвращать только те результаты, которые вы хотите, вы можете без проблем использовать нумерацию SQL. Затем вы повторно запускаете основной запрос, без нумерации страниц, но с использованием условия, когда идентификатор находится в одном из возвращенного списка. Я создал общий метод, который принимает критерии, просматривает возвращенные идентификаторы и добавляет их в качестве условия к основным критериям. Код ниже:

public static void LimitCriteriaByPrimaryKeys(this NHibernate.ICriteria criteria, string primaryKeyName, int pageNum, int pageSize)
    {
        var session = NHManager.Instance.GetCurrentSessionFromContext();
        if (pageSize <= 0) pageSize = Int32.MaxValue - 1;
        var nhSession = NHManager.Instance.GetCurrentSessionFromContext();
        var pagingCriteria = (ICriteria)criteria.Clone();
        IList ids = null;
        var pKeyIDName = Projections.Property(primaryKeyName);  
        var pKeyProjection = Projections.Distinct(pKeyIDName); 
        {
            {
                //paging
                pagingCriteria.SetProjection(pKeyProjection); //sets the primary key distinct projection
                if (pageSize > 0)
                {

                    if (pageNum < 1)
                        pageNum = 1;
                    int skipAmt = (pageNum - 1) * pageSize;
                    pagingCriteria.SetFirstResult(skipAmt);
                    pagingCriteria.SetMaxResults(pageSize); 

                    ids = pagingCriteria.List(); //this returns the distinct list of IDs which should be returned for the given page & size

                }
            }
        }
        {
            if (ids != null && ids.Count > 0)
            {
                criteria.Add(Expression.In(pKeyIDName, ids));   //adds the primary key restriction
                var crit = criteria;
                crit.SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer());
            }
            else
            {
                criteria.Add(Expression.Eq(pKeyIDName, 0)); //this is added specifically so that the main criteria returns NO results
                criteria.Add(Expression.Eq(pKeyIDName, 1));
            }
        }
    }

Методы NHManager.Instance.GetCurrentSessionFromContext(); можно заменить собственным методом для получения текущего сеанса из фабрики сеансов.

Надеюсь, это поможет!

1 голос
/ 14 мая 2011

Сочетать пейджинг и активное получение данных сложно.

Если вы укажете выборку для выбора через Criteria API, тогда каждый элемент в TrackPrices будет загружен в отдельном запросе - проблема N + 1.Вам вообще не нужно беспокоиться об активной загрузке.

Вы можете установить размер пакета для TrackPrices в отображении, чтобы облегчить проблему N + 1.В этой статье .

есть некоторые подробности о том, как смешивать выборку и пейджинг.
1 голос
/ 19 апреля 2011

Я знаю, что это не то, что вы просили, но в худшем случае вы можете инкапсулировать свои магические строки безопасным для типов способом, используя различные методологии здесь: C # String enums

...