NHibernate QueryOver и string.format

#c# #nhibernate #queryover

#c# #nhibernate #переадресация запросов

Вопрос:

Я работаю с QueryOver в NHibernate и хочу настроить одно свойство моего проектируемого DTO, используя следующий синтаксис:

 IEnumerable<PersonResponseMessage> persons =
    session.QueryOver<PersonEntity>()
        .SelectList(list => list
            .Select(p => p.Active).WithAlias(() => dto.Active)
            .Select(p => p.Alert).WithAlias(() => dto.Alert)
            .Select(p => p.Comments).WithAlias(() => dto.Comments)
            .Select(p => string.Format("{0}api/Person/{1}", uriHelper.Root, p.Id)).WithAlias(() => dto.DetailsUrl)
        )
        .TransformUsing(Transformers.AliasToBean<PersonResponseMessage>())
        .List<PersonResponseMessage>();
  

К сожалению, NHibernate не может этого сделать и выдает исключение, в котором говорится, что:

Переменная P, на которую ссылается область «», не определена

Ответ №1:

Обычно существует два способа. Частично мы можем перенести эту операцию объединения на сторону базы данных, как описано здесь:

В этом случае мы будем использовать Projections.Concat :

 .SelectList(list => list
    .Select(p => p.Active).WithAlias(() => dto.Active)
    .Select(p => p.Alert).WithAlias(() => dto.Alert)
    .Select(p => p.Comments).WithAlias(() => dto.Comments)

    // instead of this
    //.Select(p => string.Format("{0}api/Person/{1}", uriHelper.Root, p.Id))
    //       .WithAlias(() => dto.DetailsUrl)

    // use this
    .Select(p => Projections.Concat(uriHelper.Root, Projections.Concat, p.Id))
           .WithAlias(() => dto.DetailsUrl)
    )
    .TransformUsing(Transformers.AliasToBean<PersonResponseMessage>())
    .List<PersonResponseMessage>();
  

Но я бы проголосовал за обработку после публикации на уровне приложений на C#:

 .SelectList(list => list
    .Select(p => p.Active).WithAlias(() => dto.Active)
    .Select(p => p.Alert).WithAlias(() => dto.Alert)
    .Select(p => p.Comments).WithAlias(() => dto.Comments)

    // just the ID
    .Select(p => p.Id).WithAlias(() => dto.Id)
    )
    .TransformUsing(Transformers.AliasToBean<PersonResponseMessage>())
    .List<PersonResponseMessage>()
    // do the concat here, once the data are transformed and in memory
    .Select(result => 
    {
        result.DetailsUrl = string.Format("{0}api/Person/{1}", uriHelper.Root, p.Id)
        return resu<
    });
  

Комментарии:

1. Работают отлично, второй вариант мне нравится больше, потому что он работает с данными, уже находящимися в памяти