Стремительная загрузка связанных сущностей из табличной функции в NHibernate
Итак, в моей базе данных есть табличная функция, которая выполняет тяжелый и сложный запрос на основе нескольких параметров и возвращает, например, три столбца: OrderId
, SomeCalc1
, SomeCalc2
,
Теперь, чтобы перевести это в NHibernate, единственное решение, которое я нашел, - это использование именованных запросов. Мое сопоставление выглядит следующим образом:
<class name="OrderWithSomeExtraInfo">
<id name="OrderId" column="OrderId"/>
<many-to-one name="Order" update="false" insert="false">
<column name="OrderId"/>
</many-to-one>
<property name="SomeCalc1" column="SomeCalc1" update="false" insert="false"/>
<property name="SomeCalc2" column="SomeCalc2" update="false" insert="false"/>
</class>
<sql-query name="GetOrdersWithSomeCalc">
<return class='MyDomain.OrderWithSomeExtraInfo, MyDomain' alias='o'/>
<![CDATA[
SELECT F.SomeCalc1 AS {o.SomeCalc1}, F.SomeCalc2 AS {o.SomeCalc2}, F.OrderId AS {o.OrderId}
FROM [dbo].[funcSomething] ( :Param1, :Param2, :StartDate, :EndDate ) AS F
]]>
</sql-query>
И тогда в коде я звоню со следующим:
IEnumerable<OrderWithSomeExtraInfo> query =
Session.GetNamedQuery("GetOrdersWithSomeCalc")
.SetString("Param1", p1)
.SetString("Param2", p2)
.SetDateTime("StartDate", StartDate)
.SetDateTime("EndDate", EndDate)
.Future<OrderWithSomeExtraInfo>();
И то, что я хотел бы сделать, это в коде, стремятся получить также Order
свойство OrderWithSomeExtraInfo, а также некоторые цепочки многие-к-одному. Что-то вроде этого:
IEnumerable<OrderWithSomeExtraInfo> query =
Session.GetNamedQuery("GetOrdersWithSomeCalc")
.SetString("Param1", p1)
.SetString("Param2", p2)
.SetDateTime("StartDate", StartDate)
.SetDateTime("EndDate", EndDate)
.Fetch(owse => owse.Order)
.ThenFetch(o => o.Customer)
.Future<OrderWithSomeExtraInfo>();
Однако я не могу найти способ сделать это, так как это не запрос NHibernate LINQ. Так что я не знаю, как стремиться к извлечению, когда источником является собственный запрос SQL, и как сопоставить функцию с API LINQ или QueryOver.
2 ответа
Попробуйте изменить свой именованный запрос на что-то вроде этого:
<sql-query name="GetOrdersWithSomeCalc">
<![CDATA[
SELECT *
FROM [dbo].[funcSomething] (:Param1,:Param2,:StartDate,:EndDate ) as F
JOIN [dbo].[Orders] O ON F.OrderId = O.OrderId
JOIN [dbo].[Customers] C ON O.CustomerId = C.CustomerId
]]>
<return alias='f' class='MyDomain.OrderWithSomeExtraInfo, MyDomain'/>
<return-join alias='o' property='f.Order' />
<return-join alias='c' property='o.Customer' />
</sql-query>
Это должно "охотно" заполнить ваш объект (используя ваш первый пример, нет необходимости в операторах.Fetch или.FetchNext). Я экстраполировал имена таблиц и имена столбцов Id; вам может понадобиться настроить их в соответствии с соглашением об именах.
Сначала я должен извиниться, так как я не очень много знаю о NHibernate, но так как никто еще не ответил, я приложу все усилия, чтобы поделиться некоторой информацией, которую я нашел.
Это очень хорошая статья Aende, создателя NHibernate. Он объяснил, как вы можете использовать хранимую процедуру с пользовательским SQL и сущностями, которые живут в отношениях. https://ayende.com/blog/1692/using-nhibernate-with-stored-procedures
Похоже, что если вы хотите, чтобы ассоциация заказала и заказчику (<- это то, что я понимаю), то вы должны также смоделировать ее (или отобразить в своем xml).
В середине статьи есть то, что вы можете искать. Вот как то <loader query-ref="allSalariesForEmployee"/>
в статье, которая должна нести ответственность за объединение. Это также должно быть возможно, если связанный не происходит из хранимой процедуры.
Надеюсь, это поможет, и я правильно поняла ваш вопрос.