C# nHibernate中连接的筛选

C# nHibernate中连接的筛选,c#,nhibernate,C#,Nhibernate,我正在尝试构建一个nHibernate标准表达式来执行搜索 给定以下数据模型: 一个操作可以有零个或多个 会议 一个操作可以是零或零 更多操作类型 我希望根据以下条件搜索所有会话: (强制)在何处进行操作 IsActive标志为真,已发布 旗帜是真的 o(可选)且操作状态/结束日期在用户指定的日期范围内 o(可选),其中会话regionid与用户指定的id匹配 o(可选),其中会话分区与用户指定的id匹配 o(可选),其中Operation.OperationTypes位于用户指定的类型

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

给定以下数据模型:

  • 一个操作可以有零个或多个 会议
  • 一个操作可以是零或零 更多操作类型
我希望根据以下条件搜索所有会话:

  • (强制)在何处进行操作 IsActive标志为真,已发布 旗帜是真的
o(可选)且操作状态/结束日期在用户指定的日期范围内

o(可选),其中会话regionid与用户指定的id匹配

o(可选),其中会话分区与用户指定的id匹配

o(可选),其中Operation.OperationTypes位于用户指定的类型ID列表中

我将用sql将其表示为(假设已提供所有可选参数):

选择
[会议]*
从…起
[操作类型操作]
左外连接
[OperationTypeOperation].[OperationId]=[Operation].[OperationId]上的[Operation]
右外连接
[Operation].[OperationId]=[Session].[OperationId]上的[Session]
哪里
([Operation].[IsPublished]=1)
及
([Operation].[IsActive]=1)
及
([会话].[区域ID]=66)
及
([Session].[DivisionId]=99)
及
([Operation]。[AdvertisingStartDate]GETDATE())
及
((1,2,3)中的[OperationTypeOperation]。[OperationTypeId]
在我的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);
        }
public PagedResult搜索(int?regionId、int?divisionId、DateTime?startDate、DateTime?endDate、IList operationTypeId、int itemsPerPage、int page)
{
var-criteria=_session.CreateCriteria(会话类型))
.Add(表达式.Eq(“IsActive”,真))
.Add(Expression.Eq(“AcceptingApplications”,true))
.AddOrder(新订单(“起始日期”,错误))
;
if(regionId.HasValue)
添加(Expression.Eq(“Region.Id”,regionId.Value));
if(分区ID.HasValue)
添加(Expression.Eq(“Division.Id”,Division.Id.Value));
if(起始日期HasValue)
添加(Expression.Ge(“StartDate”,StartDate.Value));
if(endDate.HasValue)
添加(Expression.Le(“EndDate”,EndDate.Value));
//添加操作类型
如果(operationTypeId.Count>0)
{
var operationTypes=新集合();
foreach(operationTypeId中的int id)
{
operationTypes.Add(_session.Get(id));
}
//参加行动
criteria.CreateCriteria(“操作”)
.Add(Expression.Eq(“IsPublished”,true))
.Add(表达式.Eq(“IsActive”,真))
.Add(Expression.Le(“AdvertisingStartDate”,DateTime.Now))
.Add(Expression.Ge(“advisingenddate”,DateTime.Now))
.CreateAlias(“OperationTypes”、“OperationTypes”、JoinType.InnerJoin)
.Add(Expression.In(“OperationTypes”,OperationTypes))
.SetResultTransformer(新DistincTrotentyResultTransformer())
;
}
其他的
{
//参加行动
criteria.CreateCriteria(“操作”)
.Add(Expression.Eq(“IsPublished”,true))
.Add(表达式.Eq(“IsActive”,真))
.Add(Expression.Le(“AdvertisingStartDate”,DateTime.Now))
.Add(Expression.Ge(“advisingenddate”,DateTime.Now))
;
}
返回条件.ToPagedResult(itemsPerPage,第页);
}

我的nHibernate函数正在抱怨操作类型,并引发异常“无法使用带非表达式的集合”。另外,我也不确定是否正确过滤了连接的表。有人能以正确的方式将上述sql编写为nHibernate表达式吗?

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

criteria
  .CreateCriteria("Operation")
  // add other expressions
  .CreateCriteria("OperationTypes", "operationTypes", JoinType.LeftOuterJoin)
  .Add(Expression.In("operationTypes.Id", operationTypeId))
我假设_session.Get(id)执行数据库查询。无论如何,你应该避免这样做


PS:如果OperationType映射为复合集合(带有
标记),则很遗憾,您无法使用条件将其加入。我不确定是否有解决办法。但是还有一个补丁有待解决。

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

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