我们有这样一个实体:
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)
});
我没有其他线索。还有其他想法吗?
答案 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
,即Region
,ShowCount
和NotShowCount
< / p>