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)). И это странно, потому что 'Query () .Sum (x => x.A + x.B + x.C)' работает. К сожалению, я должен использовать QueryOver –

+0

Ну, вы можете определить оператор '+', а затем вложить его в вызовы '-'. Но да, не идеальный. –

 Смежные вопросы

  • Нет связанных вопросов^_^