#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")
)