NHibernate选择复数和

时间:2016-12-26 15:38:58

标签: nhibernate queryover nhibernate-projections

我有一个实体:

    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 }));

但我不想使用字符串。如何以其他方式完成?

1 个答案:

答案 0 :(得分:2)

不幸的是,NHibernate没有内置的算术运算符。捎带this question and answer,这里有几个选项:

  1. 直接使用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?>()
    

    这是实现这一目标最直接的方法,但有几种方法可以打扮。

  2. 创建自己的方言并注册-函数:

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

    这基本上允许您在每次使用时避免重新定义-函数,并且更加清晰。

  3. 您可以更进一步,将投影重构为扩展方法:

    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?>()
    
  4. 所有这些都会生成以下SQL:

    SELECT
        sum(this_.A - this_.B - this_.C) as y0_ 
    FROM
        Entity this_