1

我有一个实体:NHibernate的选择复数总和

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

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

回答

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

所有这些生成的SQL语句:

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

谢谢。您的解决方案适用于我的案例。但我想没有办法处理不同运营商的总和(例如SUM(A-B + C))。这很奇怪,因为'查询().Sum(x => x.A + x.B + x.C)'起作用。不幸的是,我必须使用QueryOver –

+0

那么,您可以定义一个'+'运算符,然后使用'-'调用嵌套它。但是,不理想。 –