2012-05-29 2 views
7

У меня есть список всех различных имен учетной записи префиксов (Az), которые я приобретаю, используяGroupBy SqlFunction на QueryOver

var accounts = this.SessionManager.GetActiveSession().QueryOver<Account>(); 

var q = accounts.Select(Projections.Distinct(
     Projections.SqlFunction("substring", 
           NHibernateUtil.String, 
           Projections.Property("Name"), 
           Projections.Constant(1), 
           Projections.Constant(1)))); 

Однако то, что я хочу сделать, это вместо того, чтобы вернуться отчетливый список является группа префиксы и возврат количество учетных записей, которые начинаются с этого префикса, но я не уверен, как выполнять группу, используя запрос, поскольку это не так просто, как стандартный linq.

Причина, по которой я использую QueryOver, а не запрос, потому что по какой-либо причине функция подстроки выполняется в памяти, а не на сервере базы данных.

Это, как я обычно это сделать

var prefixes = (from acc in this.SessionManager.GetActiveSession().Query<Account>() 
       group acc by acc.Name.Substring(0, 1) 
       into grp 
       select new 
         { 
         Prefix = grp.Key, 
         Count = grp.Count() 
         }); 

Редактировать Это то, что я пытался, но я получил следующее сообщение об ошибке

Непризнанный вызова метода в выражении SqlFunction ("подстрока ", NHibernateUtil.String, new [] {Property (" Name "), Constant (Convert (1)), Constant (Convert (1))})

var accounts = this.SessionManager.GetActiveSession().QueryOver<Account>().Select(
      Projections.Group<string>(x => Projections.SqlFunction("substring", NHibernateUtil.String, 
                 Projections.Property("Name"), Projections.Constant(1), 
                 Projections.Constant(1))), 
      Projections.Count<string>(x => Projections.SqlFunction("substring", NHibernateUtil.String, 
                 Projections.Property("Name"), Projections.Constant(1), 
                 Projections.Constant(1))) 

     ); 

ответ

4

Вы можете сделать это с помощью Projections.SqlGroupProjection, если все остальное не удастся!

var accounts = _busDb.Session.QueryOver<QueueEntity>() 
     .Select(
      Projections.SqlGroupProjection(
       "SUBSTRING({alias}.Name, 1) as FirstChar", 
       "SUBSTRING({alias}.Name, 1)", 
       new[] {"FirstChar"}, 
       new[] {NHibernateUtil.String}), 
      Projections.Count("id")); 

Первый аргумент является то, что выбирается в избранных, второй аргумент является то, что сгруппированы по третий аргумент является именем столбца (ов), которые выбраны, и четвертый аргумент типа выбранных данных.

+0

Функция подстроки потребовала дополнительного параметра, но это решило проблему. Большое спасибо – JConstantine

3

Какой у вас большой список? Если она меньше, чем 1000, я бы собрать список элементов из SQL Server затем выполняет свою обычную группу по запросу со списком

var sqlout= (from acc in this.SessionManager.GetActiveSession().Query<Account>() 
      select new 
        { 
        Name = acc.Name, 
        col1= acc.col1 
        }).TolList(); 

, а затем

var prefixes = (from acc in sqlout 
      group acc by acc.Name.Substring(0, 1) 
      into grp 
      select new 
        { 
        Prefix = grp.Key, 
        Count = grp.Count() 
        }); 

Substring функция будет работать здесь, так как его бег на C# список не на сервере sql

+0

На данный момент мы просматриваем списки с более чем 20-разрядными учетными записями. :( – JConstantine

3

Вы считаете, что вам нужно исключить запрос подстроки, сохранив первый символ имени в отдельном столбце?

Предполагая, что вы используете SQL Server, вы можете сделать это постоянным вычисленным столбцом, чтобы избежать необходимости обновлять код, который вставляет/обновляет таблицу.

Возможность добавления индекса, содержащего этот столбец, также должна помочь вам повысить производительность вашего запроса.

+0

+1 В качестве долгосрочного решения это, вероятно, будет так, как нам придется решать эту проблему. разум – JConstantine