Использование несопоставленного класса с именованным запросом NHibernate
-
20-08-2019 - |
Вопрос
Я использую пользовательский именованный запрос с NHibernate, который я хочу вернуть коллекцию объектов Person.Объект Person не сопоставлен с отображением NHibernate, что означает, что я получаю следующее исключение:
Система.Коллекции.Общее исключение.KeyNotFoundException:Данный ключ отсутствовал в словаре .
Он генерируется при создании сеанса, потому что он не может найти имя класса при вызове NHibernate.Cfg.Mappings.getClass(строковое имя_класса).Все это довольно понятно, но мне было интересно, есть ли какой-нибудь способ сообщить NHibernate использовать класс, даже если у меня нет сопоставления для него?
Решение 5
Чтобы решить эту проблему, я закончил тем, что использовал TupleToPropertyResultTransformer и предоставил список значений свойств.На это есть несколько ограничений, основное из которых заключается в том, что SQL-запрос должен возвращать результаты в том же порядке, в каком вы предоставляете свои свойства конструктору TupleToPropertyResultTransformer.
Также выводятся типы свойств, поэтому вам нужно быть осторожным с десятичными столбцами, возвращающими только целочисленные значения и т.д.Кроме того, использование TupleToPropertyResultTransformer предоставило достаточно простой способ использовать SQL-запрос для возврата коллекции объектов без явного отображения объектов в NHibernate.
Другие советы
Почему бы вам не использовать:
query.SetResultTransformer(Transformers.AliasToBean(typeof(Person)));
Он вставит данные из каждого столбца вашего запроса в свойства объекта Person, используя псевдоним столбца в качестве имени свойства.
Как вы можете создать запрос , который возвращал бы экземпляры типа , который не сопоставлен ?
Я думаю, что Михал здесь прав, и, возможно, вам стоит взглянуть на прогнозы.(По крайней мере, это то, что, я думаю, вы ищете).
Вы создаете запрос к некоторому сопоставленному типу, а затем можете "спроецировать" этот запрос в "DTO".Чтобы сделать это, вам нужно будет "импортировать" свой класс Person, чтобы он был известен NHibernate, и вам придется использовать ResultTransformer .
Что- то вроде этого:
ICriteria crit = session.CreateCriteria (typeof(Person));
// set some filter criteria
crit.SetProjection (Projections.ProjectionList()
.Add (Property("Name"), "Name")
.Add (Property( ... )
);
crit.SetResultTransformer(Transformers.AliasToBean(typeof(PersonView));
return crit.List<PersonView>();
Но это все равно означает, что вам придется импорт класс, чтобы NHibernate знал об этом.
Используя класс, NHibernate в основном догадывался бы обо всем, что связано, включая, какую таблицу вы намеревались использовать для Person, и сопоставления полей.NHibernate, вероятно, можно было бы взломать для выполнения динамической привязки на основе сопоставления имен или чего-то еще, но вся идея состоит в том, чтобы создать сопоставления из простого старого объекта data с полями базы данных, используя xml-файлы.
Если нет действительно веской причины не сопоставлять класс, простое добавление сопоставления даст вам наилучшие результаты...
Тем не менее, вы не можете использовать именованный запрос для прямого ввода результатов в несопоставленный класс.Вам нужно было бы указать ему, какие столбцы помещать в какие поля, или, другими словами, сопоставление.;) Однако вы можете возвращать скалярные значения из именованного запроса, и вы могли бы взять эти массивы объектов и создать свою коллекцию вручную.