如何编写这个Linq到NHibernate查询

时间:2015-04-28 09:19:46

标签: c# linq nhibernate

我们有这样一个实体:

public class File{
       public int Region{get;set;}
       public bool ShowLocation{get;set;}
       //Other fields are omitted
}

我想写这个查询:

    SELECT Region,SUM(CASE WHEN ShowLocation=1 THEN 1 ELSE 0 END) AS
 ShowCount,SUM(CASE WHEN ShowLocation=0 THEN 1 ELSE 0 END) AS NotShowCount
--WHERE omitted for the sake of simplicity
GROUP BY Region

出于某些原因,我想使用Linq To Nhibernate(我们有一个生成Expression<Func<File,bool>>的复杂过滤机制)

到目前为止,我找不到使用Linq To NHibernate实现此目的的任何方法。 这是我的一些尝试:

Conditioanl Count :(没有例外,但无论如何它都计算所有行)

    Files
    .Where(whereExpression)
    .GroupBy(x=>x.Region)
    .Select(x=>new
    {
        x.Region,
        ShowCount=x.Count(f=>f.ShowLocation==1),
        NotShowCount=x.Count(f=>f.ShowLocation==0)
    });

Conditioanl Sum:不支持/实现异常

Files
.Where(whereExpression)
.GroupBy(x=>x.Region)
.Select(x=>new 
{
  x.Region,
  ShowCount=x.SUM(f=>f.ShowLocation==1?1:0),
  NotShowCount=x.SUM(f=>f.ShowLocation==0?1:0)
});

GROUP之前的SELECT:不支持/实现异常

    Files.Where(whereExpression).Select(x=>new
    {
       x.Region,
       Show=x.ShowLocation==1?1:0,
       NotShow=x.ShowLocation==0?1:0
    })
    .GroupBy(x=>x.Region)
    .Select(x=>new 
    {
       x.Region,
       ShowCount=x.SUM(f=>f.Show),
       NotShowCount=x.SUM(f=>f.NotShow)
    });

UNION:不支持/实现异常

    Files
       .Where(whereExpression)
       .Where(x=>x.ShowLocation==1)
 .Select(x=>new
{
x.Region,
Show=1,NotShow=0
})
.Union(Files
 .Where(whereExpression)
.Where(x=>x.ShowLocation==0)
.Select(x=>new
{x.Region,
Show=0,
NotShow=1
}))
.GroupBy(x=>x.Region)
.Select(x=>new 
{
x.Region,
CountShow=x.Count(a=>a.Show),
CountNotShow=x.Count(a=>a.NotShow)
});

我没有其他线索。还有其他想法吗?

2 个答案:

答案 0 :(得分:1)

我使用了您的第二次尝试,并在ToList()之前插入了Select()。结果看起来像这样:

Files
.Where(whereExpression)
.GroupBy(x=>x.Region)
.ToList<IGrouping<int, File>>()
.Select(x=>new 
{
  x.Key,
  ShowCount = x.Sum(f => f.ShowLocation == 1 ? 1 : 0),
  NotShowCount = x.Sum(f => f.ShowLocation == 0 ? 1 : 0)
});

以这种方式,Select将应用于List而不是IQueryable。

答案 1 :(得分:0)

我不知道你能不能和Linq一起工作到NH。您是否可以使用QueryOver? QueryOver API在where子句中也使用Expression<Func<T,bool>>,因此您应该可以使用现有的过滤器使其工作:

            MyDto dto = null;

            var myDtoList = session.QueryOver<File>()
                .Select(
                    Projections.Group<File>(x => x.Region).WithAlias(() => dto.Region),
                    Projections.Sum(
                        Projections.Conditional(
                            Restrictions.Where<File>(c => c.ShowLocation== 1),
                            Projections.Constant(1),
                            Projections.Constant(0))).WithAlias(() => dto.ShowCount),
                    Projections.Sum(
                        Projections.Conditional(
                            Restrictions.Where<File>(c => c.ShowLocation== 0),
                            Projections.Constant(1),
                            Projections.Constant(0))).WithAlias(() => dto.NotShowCount))
                .TransformUsing(Transformers.AliasToBean<MyDto>())
                .List<MyDto>();

QueryOver并不真正适用于匿名类型,因此您必须使用要返回的属性定义MyDto,即RegionShowCountNotShowCount < / p>