NHibernate: ярлык для проецирования всех свойств?

#nhibernate #icriteria #queryover

#nhibernate #icriteria #выполнение запроса

Вопрос:

Я пытаюсь сгенерировать SQL в соответствии с:

 SELECT 
  t.*, 
  SELECT (...)
FROM Title t
[trimmed]
  

использование запроса

 Title title = null;

var q = session
   .QueryOver(() => title)
   .Select(
      Projections.Alias(Projections.Property<Title>(t => t.Id), "Id"),
      Projections.Alias(Projections.Property<Title>(t => t.Name), "Name"),
      ....
      Projections.SubQuery(sq.Where(tt => tt.Id == title.Id))), "TopLevelGenre")
)
[code trimmed]
  

В Title есть 15 свойств, которые я хотел бы спроецировать. Есть ли более простой способ сделать это, чтобы мне не приходилось проецировать каждое свойство по отдельности, как я начал делать выше?

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

1. Я так понимаю, вы не хотите использовать HQL ?

2. Я предпочитаю ICriteria, но я открыт для использования HQL. Что вы имели в виду?

3. Кроме того, если код, который я опубликовал выше, является единственным способом сделать это с помощью ICritiera, я был бы признателен за подтверждение.

Ответ №1:

Если вы не возражаете против ICriteria, это работает. Я тестировал с 2.1.2, но я не понимаю, почему if не будет работать с 3.x.

 var projectionList = Projections.ProjectionList();
var metadata = session.SessionFactory.GetClassMetadata(typeof(Title));
foreach (var name in metadata.PropertyNames)
{
    projectionList.Add(Projections.Property(name), name);
}
var criteria = DetachedCriteria.For<Title>()
   .SetProjection(projectionList)
   ...;
  

Ответ №2:

Я обнаружил, что начиная с NHibernate 3.2, это невозможно без ручного перечисления всех свойств.

Ответ №3:

Это невозможно сделать без ручного перечисления всех свойств. Обычно я использую CodeSmith для генерации кодов проекций.

Ответ №4:

Если вам нужны объекты Title, вы можете просто написать:

 IList<Title> list = session.QueryOver<Title>.Where(/*some condition*/).List();  
  

NHibernate заполнит все атрибуты заголовка для вас.

смотрите здесь для получения дополнительной информации.

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

1. спасибо за ваш ответ. Однако это не то, что я ищу. Как вы можете видеть в опубликованном мной коде, я пытаюсь выбрать все значения в таблице Title в дополнение к значению, которое генерируется подзапросом.

Ответ №5:

Возможно ли создать представление в таблице title с интересующими вас столбцами? или, возможно, вы захотите попробовать разделить свойства класса Title на два класса (класс TitleBase и класс Title, который наследуется от класса TitleBase). Соответственно, вам нужно создать два отдельных файла сопоставления.

Предположим, что все интересующие вас свойства находятся в классе TitleBase, затем используйте его в вышеупомянутом запросе.

Ответ №6:

Я решил это с помощью этого кода. Я надеюсь, что это может вам пригодиться. Я просто использую пакеты, просто измените сравнение, если вам нужно использовать, например, ISet. PDM — это объект, к свойствам которого я применяю отражение. Вы могли бы изменить этот метод, чтобы он был универсальным.

         ProjectionList list = Projections.ProjectionList();            
        var metadata = session.SessionFactory.GetClassMetadata(typeof(PDM));

        foreach (var name in metadata.PropertyNames)
        {
            PropertyInfo property = typeof(PDM).GetProperties(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(x => x.Name.Equals(name));
            FieldInfo field = typeof(PDM).GetFields(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(x => x.Name.Equals(name));

            if (property != null)
            {
                if (!property.PropertyType.Name.Contains("IList"))
                {
                    list.Add(Projections.Property(name), name);
                }
            }

            if (field != null)
            {
                if (!field.FieldType.Name.Contains("IList"))
                {
                    list.Add(Projections.Property(name), name);
                }
            }
        }          
  

Ответ №7:

Это возможно в NHibernate 5.1 с помощью проекций сущностей:

 Title title = null;

var q = session
   .QueryOver(() => title)
   .Select(
      Projections.Entity(() => title),
      Projections.SubQuery(sq.Where(tt => tt.Id == title.Id))), "TopLevelGenre")
)