Фильтр объединений в nHibernate - PullRequest
4 голосов
/ 02 марта 2009

Я пытаюсь построить выражение критерия nHibernate для выполнения поиска.

Учитывая следующую модель данных:

  • Операция может иметь ноль или более сессий.
  • Операция может иметь ноль больше типов операций.

Я хочу найти все сеансы по следующим критериям:

  • (обязательно), где операция IsActive флаг является истинным, IsPublished флаг верный

o (Опционально) и где состояние операции / даты окончания находятся в пределах указанного пользователем диапазона дат

o (необязательно) и где regionid сеанса соответствует указанному пользователем идентификатору

o (необязательно) и где разделение сеанса соответствует указанному пользователем идентификатору

o (необязательно) и где Operation.OperationTypes находятся в указанном пользователем списке идентификаторов типов

Я бы выразил это в sql как (учитывая все необязательные параметры были предоставлены):

SELECT     
    [Session].*
FROM         
    [OperationTypeOperation] 
LEFT OUTER JOIN
    [Operation] ON [OperationTypeOperation].[OperationId] = [Operation].[OperationId]
RIGHT OUTER JOIN
    [Session] ON [Operation].[OperationId] = [Session].[OperationId]
WHERE
    ([Operation].[IsPublished] = 1) 
AND 
    ([Operation].[IsActive] = 1) 
AND 
    ([Session].[RegionId] = 66)
AND 
    ([Session].[DivisionId] = 99)
AND 
    ([Operation].[AdvertisingStartDate] < GETDATE()) 
AND 
    ([Operation].[AdvertisingEndDate] > GETDATE()) 
AND 
    ([OperationTypeOperation].[OperationTypeId] IN (1, 2, 3))

И в моем запросе nHibernate как:

public PagedResult<Session> Search(int? regionId, int? divisionId, DateTime? startDate, DateTime? endDate, IList<int> operationTypeId, int itemsPerPage, int page)
        {

            var criteria = _session.CreateCriteria(typeof(Session))
                .Add(Expression.Eq("IsActive", true))
                .Add(Expression.Eq("AcceptingApplications", true))
                .AddOrder(new Order("StartDate", false))
                ;

            if (regionId.HasValue)
                criteria.Add(Expression.Eq("Region.Id", regionId.Value));

            if (divisionId.HasValue)
                criteria.Add(Expression.Eq("Division.Id", divisionId.Value));

            if (startDate.HasValue)
                criteria.Add(Expression.Ge("StartDate", startDate.Value));

            if (endDate.HasValue)
                criteria.Add(Expression.Le("EndDate", endDate.Value));

            //Add the operation types
            if (operationTypeId.Count > 0)
            {
                var operationTypes = new Collection<OperationType>();
                foreach (int id in operationTypeId)
                {
                    operationTypes.Add(_session.Get<OperationType>(id));
                }
                //Join on the operations
                criteria.CreateCriteria("Operation")
                .Add(Expression.Eq("IsPublished", true))
                .Add(Expression.Eq("IsActive", true))
                .Add(Expression.Le("AdvertisingStartDate", DateTime.Now))
                .Add(Expression.Ge("AdvertisingEndDate", DateTime.Now))
                .CreateAlias("OperationTypes", "operationTypes", JoinType.InnerJoin)
                .Add(Expression.In("OperationTypes", operationTypes))
                .SetResultTransformer(new DistinctRootEntityResultTransformer())
                ;
            }
            else
            {
                //Join on the operations
                criteria.CreateCriteria("Operation")
                .Add(Expression.Eq("IsPublished", true))
                .Add(Expression.Eq("IsActive", true))
                .Add(Expression.Le("AdvertisingStartDate", DateTime.Now))
                .Add(Expression.Ge("AdvertisingEndDate", DateTime.Now))
                ;
            }

            return criteria.ToPagedResult<Session>(itemsPerPage, page);
        }

Моя функция nHibernate жалуется на типы операций и выдает исключение «Невозможно использовать коллекции с InExpression». Кроме того, я не уверен, правильно ли я фильтрую объединенные таблицы. Может кто-нибудь правильно взвесить, чтобы написать выше SQL как выражение nHibernate?

Ответы [ 2 ]

5 голосов
/ 15 апреля 2009

Я предполагаю, что OperationType является классом сущности (не перечислением). Вы не можете использовать In со списком объектов. Вы можете присоединиться, используя идентификатор.

criteria
  .CreateCriteria("Operation")
  // add other expressions
  .CreateCriteria("OperationTypes", "operationTypes", JoinType.LeftOuterJoin)
  .Add(Expression.In("operationTypes.Id", operationTypeId))

Я предполагаю, что _session.Get (id) выполняет запрос к базе данных. Вам все равно следует избегать этого.

PS: если OperationType отображается как составная коллекция (с тегом <composite-element>), то, к сожалению, вы не можете присоединить его с критериями. Я не уверен, что есть обходной путь. Но есть патч в ожидании.

1 голос
/ 05 января 2010

Я думаю, что есть лучший способ, чем писать:

criteria
  .CreateCriteria("Operation")
  // add other expressions
  .CreateCriteria("OperationTypes", "operationTypes", JoinType.LeftOuterJoin)
  .Add(Expression.In("operationTypes.Id", operationTypeId))

потому что дополнительное соединение выполняется на "Operation"

Вы можете просто написать:

criteria.Add(Expression.In("OperationTypes", operationTypeId))
.CreateCriteria("Operation")
                        .Add(Expression.Eq("IsPublished", true))
                        .Add(Expression.Eq("IsActive", true))
                        .Add(Expression.Le("AdvertisingStartDate", DateTime.Now))
                        .Add(Expression.Ge("AdvertisingEndDate", DateTime.Now))
                        .SetResultTransformer(new DistinctRootEntityResultTransformer())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...