Select 计算列值时的NHibernate查询覆盖情况

Select 计算列值时的NHibernate查询覆盖情况,select,nhibernate,case,queryover,Select,Nhibernate,Case,Queryover,我一直试图在NHibernate QueryOver中执行以下T-SQL,但没有成功: SELECT Id, SUM(CASE MyValue WHEN 1 THEN Volume ELSE Volume * -1 END) FROM MyTable GROUP BY Id 我试图总结所有的音量,但是对于MyValue=1应该是正值,否则为负值。到目前为止,我得到了: var result = this.Session.QueryOver<MyTable>() .Sele

我一直试图在NHibernate QueryOver中执行以下T-SQL,但没有成功:

SELECT Id, SUM(CASE MyValue WHEN 1 THEN Volume ELSE Volume * -1 END)
FROM MyTable
GROUP BY Id
我试图总结所有的音量,但是对于
MyValue=1
应该是正值,否则为负值。到目前为止,我得到了:

 var result = this.Session.QueryOver<MyTable>()
    .Select(Projections.Group<MyTable>(x => x.Id),
    Projections.Conditional(Restrictions.Eq(Projections.Property<MyTable>(x
        => x.MyValue), '1'),
    Projections.Property<MyTable>(x => x.Volume),
    Projections.Property<MyTable>(x => x.Volume * -1)))
    .List();
var result=this.Session.QueryOver()
.Select(projects.Group(x=>x.Id),
投影。条件(限制。等式(投影。属性(x
=>x.MyValue),“1”),
属性(x=>x.Volume),
投影。属性(x=>x.卷*-1)))
.List();

但正如你所想象的那样,NHibernate不知道第1卷的列,那么在我的情况下,我该如何计算呢?

我认为这应该可以做到:

session.QueryOver<MyTable>()
    .Select(
        Projections.Group<MyTable>(x => x.Id),
        Projections.Sum(
            Projections.Conditional(
                Restrictions.Eq(
                    Projections.Property<MyTable>(x => x.MyValue), 1),
                Projections.Property<MyTable>(x => x.Volume),
                Projections.SqlFunction(
                    new VarArgsSQLFunction("(", "*", ")"),
                    NHibernateUtil.Int32,
                    Projections.Property<MyTable>(x => x.Volume),
                    Projections.Constant(-1)))))
    .List<object[]>();
请注意,您需要在此处使用与自定义数据配对的结果转换器,或者使用
.List
,这将结果集转换为
对象[]
列表
,列表中的每个项都是结果行。您不能只使用
.List()
,因为NHibernate希望选择整个
MyTable
行,而您在这里没有这样做

你可能认为这很难看,我也同意。您可以通过将投影重构为它们自己的变量来清理它:

IProjection multiplicationProjection = 
    Projections.SqlFunction(
        new VarArgsSQLFunction("(", "*", ")"),
        NHibernateUtil.Int32,
        Projections.Property<MyTable>(t => t.Volume),
        Projections.Constant(-1));

IProjection conditionalProjection = 
    Projections.Conditional(
        Restrictions.Eq(
            Projections.Property<MyTable>(t => t.MyValue), 1),
        Projections.Property<MyTable>(t => t.Volume),
        multiplicationProjection);

session.QueryOver<MyTable>()
    .SelectList(list => list
        .SelectGroup(t => t.Id)
        .Select(Projections.Sum(conditionalProjection)))
    .List<object[]>();
i投影乘法投影=
Projections.SqlFunction(
新的VarArgsSQLFunction(“(”,“*”,”),
NHibernateUtil.Int32,
预测。属性(t=>t.体积),
预测。常数(-1));
I预测条件预测=
预测.有条件的(
限制条件(
属性(t=>t.MyValue),1),
预测。属性(t=>t.体积),
乘法投影);
session.QueryOver()
.SelectList(list=>list
.SelectGroup(t=>t.Id)
.Select(projects.Sum(conditionalProjection)))
.List();

非常感谢Andrew-我已经阅读了你的博客,但我不认为这颗小宝石在其中:-)@mfas:我也不这么认为:)。很高兴我能帮上忙我在现实世界的例子中使用小数,NHibernate一直告诉我返回类型不一致:“true和false投影必须返回相同的类型。但是true投影返回:[NHibernate.Type.DecimalType]和false投影返回:[NHibernate.Type.DecimalType]。”这对我来说毫无意义-我当然已经将SQLFunction中的类型更改为Decimal,并尝试将常量更改为“-1.0m”,但没有任何效果。@mfas:Hmm,如果我做了这些更改,一切似乎都正常。事实上,如果我只是将SqlFunction的结果更改为
NHibernateUtil.Decimal
,我不会得到错误。在C类中,
Volume
有什么类型?我可以看到我正在处理的项目使用的是NHibernate版本3.3.3.5000。我不知道这个版本在这方面是否有缺陷。我会看看我是否可以升级到最新版本,看看这是否会有所不同。但是谢谢你帮我测试。顺便说一下,实体上的属性也是一个
十进制