English 中文(简体)
nHibernate中的连接过滤器
原标题:
  • 时间:2009-03-01 23:57:05
  •  标签:

我正尝试构建一个nHibernate标准表达式来执行搜索。

给定以下数据模型:

  • An operation may have zero or more sessions.
  • An operation may be of zero of more operation types.

我想根据以下标准搜索所有会话:

  • (Mandatory) Where the operation IsActive flag is true, IsPublished flag is true

(可选)且操作状态/结束日期在用户指定的日期范围内

(可选)且会话 regionid 与用户指定的 id 相匹配

(可选)并且会话分区与用户指定的 ID 匹配。

(可选)且Operation.OperationTypes在用户指定的类型ID列表中。

如果提供了所有可选参数,我会在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函数抱怨操作类型,并抛出一个异常“Cannot use collections with InExpression”。此外,我不确定我是否正确地筛选了连接表格。有人可以以正确的方式将上述SQL编写为nHibernate表达式吗?

问题回答

我假设OperationType是一个实体类(不是枚举)。你不能用In操作符与实体列表一起使用。你可以使用ID连接。

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

我假设_session.Get(id)执行数据库查询。无论如何,您都应该避免这种情况。

附注:如果 OperationType 被映射为复合集合(使用 <composite-element> 标签),那么很遗憾,您无法将其与条件结合起来。 我不确定是否有解决方法,但有一个补丁待处理。

我认为有比书写更好的方法:

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

因为在“操作”上执行了额外的连接。

你可以简单地写:

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())




相关问题
热门标签