Существует три основных подхода, некоторые из которых уже обсуждались:
- Использовать HQL-запрос или
CreateCriteria
/ ICriteria
запрос; минусы: это не часть сущностей / DAL; преимущества: это гибко;
- Использовать сопоставление свойств с
formula
; недостатки: это не всегда возможно или возможно, производительность может ухудшиться, если не соблюдать осторожность; Достоинства: Это расчет неотъемлемая часть вашей сущности;
- Создать отдельный файл отображения XML HBM и отобразить в отдельный (подлежащий созданию) объект; минусы: это не часть базовых сущностей; преимущества: вы вызываете SP только при необходимости, полный контроль над отображением / дополнительными свойствами / расширениями, можете использовать частичные или абстрактные классы для объединения с существующими сущностями.
Я кратко покажу пример варианта 2 и 3 здесь, я полагаю, что вариант 1 был достаточно рассмотрен другими ранее в этой теме.
Второй вариант, как в этом примере, особенно полезен, когда запрос может быть создан как подзапрос оператора select и когда все необходимые параметры доступны в отображенной таблице. Также полезно, если таблица не является изменяемой и / или кэшируется как доступная только для чтения, в зависимости от того, насколько тяжелой является ваша хранимая процедура.
<class name="..." table="..." lazy="true" mutable="false>
<cache usage="read-only" />
<id name="Id" column="id" type="int">
<generator class="native" />
</id>
<property name="Latitude" column="Latitude" type="double" not-null="true" />
<property name="Longitude" column="Longitude" type="double" not-null="true" />
<property name="PrijsInstelling"
formula="(dbo.DistanceBetween(@lat1, @lat2, Latitude, Longitude))"
type="double" />
... etc
</class>
Если вышеупомянутое невозможно из-за ограничений в отображениях, проблем с кэшированием или если ваши текущие настройки кэша извлекаются один за другим, а не большими суммами, и вы не можете это изменить, вам следует рассмотреть альтернативный подход, например отдельное отображение всего запроса с параметрами. Это очень близко к подходу CreateSqlQuery, описанному выше, но заставляет набор результатов определенного типа (и вы можете установить каждое свойство декларативно):
<sql-query flush-mode="never" name="select_Distances">
<return
class="ResultSetEntityClassHere,Your.Namespace"
alias="items"
lock-mode="read" >
<return-property name="Id" column="items_Id" />
<return-property name="Latitude" column="items_Latitude" />
<return-property name="Longitude" column="items_Longitude" />
<return-property name="Distance" column="items_Distance" />
</return>
SELECT
Items.*,
dbo.DistanceBetween(@lat1, @lat2, Latitude, Longitude) AS Distance
FROM Items
WHERE UserId = :userId
</sql-query>
Вы можете вызвать этот запрос следующим образом:
List<ResultSetEntityClassHere> distanceList =
yourNHibernateSession.GetNamedQuery("select_Distances")
.SetInt32("userId", currentUserId) /* any params go this way */
.SetCacheable(true) /* it's usually good to cache */
.List<ResultSetEntityClassHere>(); /* must match the class of sql-query HBM */
В зависимости от ваших потребностей, вы можете выбрать подход. Я лично использую следующее правило, чтобы решить, какой подход использовать:
- Является ли расчет легким или его можно кэшировать? Использовать
formula
подход;
- Нужно ли отправлять параметры в SP / SQL? Использовать
sql-query
+ картографический подход;
- Является ли структура запроса (очень) переменной? Используйте
ICriteria
или HQL подход через код.
Об упорядочении данных: когда вы выбираете «формулу» или «сопоставление sql-запроса», вам придется упорядочивать данные при извлечении данных. Это не отличается от получения данных через ваши текущие сопоставления.
Обновление: Исправлена ужасная ошибка редактирования в XML-файле sql-запроса.