В устаревшей базе данных мне приходится работать с вложенными таблицами, которые связаны через составные ключи. В переводе на NHibernate я, например, класс FcoTransproduction, который имеет коллекцию детей класса FcoConsignment. Однако в одной ситуации я хотел бы загрузить коллекцию на основе только одного из компонентов составного ключа и игнорировать другой компонент.
Отображение выглядит так:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
<class name="FcoLib.FcoTransportation, FcoLib" table="FCO_TRANSPORTATION">
<composite-id>
<key-property name="ID"/>
<key-property name="FK_EventID"/>
</composite-id>
<!--...snip...-->
<bag name="Consignments" table="FCO_Consignment" lazy="false" cascade="save-update">
<key>
<column name="FK_TransportationID"/>
<column name="FK_EventID"/>
</key>
<one-to-many class="FcoLib.FcoConsignment, FcoLib"/>
</bag>
<!--...snip...-->
Я пытался создать этот запрос, используя обычные критерии NHibernate, SQL и HQL.
Вот что я получил в HQL, что по крайней мере загружает транспорты без ошибок:
String queryString = "select ft from FcoTransportation as ft";
queryString += " join ft.Consignments as fc on fc.FK_TransportationID = :ID";
var query = session.CreateQuery(queryString);
transports = query
.SetMaxResults(100)
.List<FcoTransportation>();
Тем не менее, сбор грузов остается пустым! Как мне это решить!?
В качестве дополнения я хотел бы отсеять любые дублирующиеся дочерние элементы, выбрав те записи с наивысшими значениями в двух столбцах «ChangedDate» и «ChangedTime» соответственно.
В качестве последнего средства я рассматриваю возможность полного удаления составного сопоставления клавиш. В этом случае мне все равно придется удалять дубликаты на основе последней версии ChangedDate / ChangedTime ...
ОБНОВЛЕНИЕ : Я попытался удалить сопоставления составного ключа, но затем я получаю ошибку, которая, по-видимому, выдается, потому что составные внешние ключи применяются, даже когда я пытаюсь их игнорировать. Так что за хитрость в том, чтобы убедить NHibernate НЕ применять это, поскольку я легко могу написать SQL-запрос в SQL Srv Mgt Studio, выполнив следующее:
SELECT TOP 100 *
FROM [FCO_EVENT] AS e
INNER JOIN [FCO_TRANSPORTATION] AS t ON e.FK_TransportationID = t.ID
--children:
LEFT OUTER JOIN [FCO_CONSIGNMENT] AS c ON c.FK_TransportationID = t.ID
LEFT OUTER JOIN [FCO_CONSIGNMENT_LINES] AS cl ON cl.FK_ConsignmentID = c.ID
ОБНОВЛЕНИЕ : Было предложено использовать выборку соединения, которая выглядит многообещающе, но по-прежнему не выбираются дети:
String queryString = "select ft from FcoTransportation as ft where ft.ID ='" + guid + "'";
queryString += " join fetch ft.Consignments as fc on fc.FK_TransportationID = '" + guid + "'";
ОБНОВЛЕНИЕ : Было также предложено сделать так называемое объединение в "тэта-стиле", которое выглядит ниже, но и здесь коллекция потомков не заполняется:
String queryString = "select ft from FcoTransportation as ft, FcoConsignment as fc"
+ " where ft.ID = fc.FK_TransportationID"
+ " and ft.ID = '" + guid + "'";
ПРИМЕЧАНИЕ : Мне нужно только получить данные, а не сохранить их снова. У меня уже есть запрос на получение грузов для каждого транспорта (в большинстве случаев их десятки, но обычно несколько, а в отдельных случаях - несколько сотен). Я просто хочу быть экономичным с количеством обращений к базе данных. Вот почему я хотел бы, чтобы груз доставлялся одновременно с доставкой транспорта.