我有一个实体:
class Entity
{
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }
}
我想选择(A-B-C)的总和。所以我想像这样运行sql:
SELECT SUM(A-B-C) FROM Entity
我可以通过SqlProjection实现它:
QueryOver.Of<Entity>().Select(Projections.SqlProjection("SUM(A-B-C) AS total", new[] { "total" }, new IType[] { NHibernateUtil.Int32 }));
但我不想使用字符串。如何以其他方式完成?
答案 0 :(得分:2)
不幸的是,NHibernate没有内置的算术运算符。捎带this question and answer,这里有几个选项:
直接使用VarArgsSQLFunction
:
var subtractFunction = new VarArgsSQLFunction(string.Empty, " - ", string.Empty);
session.QueryOver<Entity>(() => entityAlias)
.Select(
Projections.Sum(
Projections.SqlFunction(
subtractFunction, NHibernateUtil.Int32,
Projections.Property(() => entityAlias.A),
Projections.Property(() => entityAlias.B),
Projections.Property(() => entityAlias.C)
)
)
)
.SingleOrDefault<int?>()
这是实现这一目标最直接的方法,但有几种方法可以打扮。
创建自己的方言并注册-
函数:
public class MyDialect : MsSql2008Dialect
{
public MyDialect()
{
this.RegisterFunction("-", new VarArgsSQLFunction(string.Empty, " - ", string.Empty));
}
}
session.QueryOver<Entity>(() => entityAlias)
.Select(
Projections.Sum(
Projections.SqlFunction(
"-", NHibernateUtil.Int32,
Projections.Property(() => entityAlias.A),
Projections.Property(() => entityAlias.B),
Projections.Property(() => entityAlias.C)
)
)
)
.SingleOrDefault<int?>()
这基本上允许您在每次使用时避免重新定义-
函数,并且更加清晰。
您可以更进一步,将投影重构为扩展方法:
public static class CustomProjections
{
public static IProjection Subtract(IType type, params IProjection[] projections)
{
return Projections.SqlFunction("-", type, projections);
}
}
session.QueryOver<Entity>(() => entityAlias)
.Select(
Projections.Sum(
CustomProjections.Subtract(
NHibernateUtil.Int32,
Projections.Property(() => entityAlias.A),
Projections.Property(() => entityAlias.B),
Projections.Property(() => entityAlias.C)
)
)
)
.SingleOrDefault<int?>()
所有这些都会生成以下SQL:
SELECT
sum(this_.A - this_.B - this_.C) as y0_
FROM
Entity this_