1

我有一个实体:

    class Entity
    {
        public int A { get; set; }
        public int B { get; set; }
        public int C { get; set; }
    }

我想选择(ABC)的总和。所以我想像这样运行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 }));

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

4

1 回答 1

2

不幸的是,NHibernate 没有内置算术运算符。捎带这个问题和答案,这里有几个选项:

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

所有这些都会生成以下 SQL:

SELECT
    sum(this_.A - this_.B - this_.C) as y0_ 
FROM
    Entity this_
于 2016-12-28T02:12:05.983 回答