【问题标题】:Filter on joins in nHibernate过滤 nHibernate 中的连接
【发布时间】:2010-10-26 19:16:06
【问题描述】:

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

给定以下数据模型:

  • 一个操作可能有零个或多个 会议。
  • 操作可能为零 更多操作类型。

我想根据以下条件搜索所有会话:

  • (强制)在哪里操作 IsActive 标志为真,IsPublished 标志为真

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

o(可选)并且会话 regionid 与用户指定的 id 匹配的位置

o(可选)并且会话划分与用户指定的 id 匹配的位置

o(可选)以及 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 函数抱怨操作类型并抛出异常“不能使用 InExpression 的集合”。另外,我不确定我是否正确过滤了连接的表。谁能以正确的方式权衡将上述 sql 写为 nHibernate 表达式?

【问题讨论】:

    标签: c# nhibernate


    【解决方案1】:

    我假设OperationType 是一个实体类(不是枚举)。您不能将In 与实体列表一起使用。您可以使用 id 加入。

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

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

    PS:如果 OperationType 被映射为复合集合(带有&lt;composite-element&gt; 标签),那么不幸的是,您不能使用条件加入它。我不确定是否有解决方法。但是有一个补丁正在等待中。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-22
        • 1970-01-01
        相关资源
        最近更新 更多