Сопоставление композитного первичного ключа с помощью внешнего ключа в nhibernate
-
12-10-2019 - |
Вопрос
Компания, в которой я работаю, использует ERP, а ее устаревшая база данных - Oracle. До сих пор я использовал пакеты (Oracle, хранящие процедуры) для доступа к данным, но в течение многих лет число стало последовательно, и теперь я больше не могу им управлять.
Я пытался провести несколько экспериментов с Nhibernate и начал отображать несколько таблиц.
Все таблицы имеют составные первичные ключи. Короткое описание:
Порядок таблицы (имя таблицы: Оксаорх)
Ochordn (Пк) => Ordernumber
Ochamnd (Пк)
Ochcosc (Пк) => Компания
Ochclii
...
Таблица orderline (имя таблицы: Оксалин)
Оклордн (Пк) => Ordernumber
ОКЛАМНД (Пк)
Oclcosc (Пк) => Компания
Ocllinn (Пк) => Номер строки
Oclsseq (Пк)
Oclitmn
...
Это мое картирование
Заказ:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="MvcOracleNhibernate"
namespace="MvcOracleNhibernate.Domain">
<class name="Order" table="OCSAORH">
<composite-id>
<key-property name="Number" column="OCHORDN"></key-property>
<key-property name="Ver" column="OCHAMND"></key-property>
<key-property name="Company" column="OCHCOSC"></key-property>
</composite-id>
<property name="CustomerCode" column="OCHCLII" type="String" length="10"></property>
<property name="Reference" column="OCHOCNO" type="String" length="25"></property>
<property name="Date" column="OCHOCDT" type="Double"></property>
<bag name="OrderLines" cascade="all-delete-orphan" generic="true" inverse="true" lazy="false">
<key>
<column name="OCLORDN" not-null="true"/>
<column name="OCLAMND" not-null="true"/>
<column name="OCLCOSC" not-null="true"/>
</key>
<one-to-many class="OrderLine" not-found="ignore"/>
</bag>
</class>
</hibernate-mapping>
Порядок:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="MvcOracleNhibernate"
namespace="MvcOracleNhibernate.Domain">
<class name="OrderLine" table="OCSALIN">
<composite-id>
<key-property name="Number" column="OCLORDN"></key-property>
<key-property name="Ver" column="OCLAMND" ></key-property>
<key-property name="Company" column="OCLCOSC"></key-property>
<key-property name="Line" column="OCLLINN"></key-property>
<key-property name="Seq" column="OCLSSEQ"></key-property>
</composite-id>
<property name="Item" column="OCLITMN" type="String" length="19"></property>
<property name="Quantity" column="OCLQTYP" type="Double"></property>
</class>
</hibernate-mapping>
С этими сопоставлениями все работает нормально; Я могу загрузить заказ, и ленивая загрузка загружает мои линии. Читая какую-то документацию, я заметил, что я не определил отношение много-одно, поэтому я добавил это:
<many-to-one name="Order" class="Order" lazy="proxy">
<column name="OCHORDN" not-null="true"/>
<column name="OCHAMND" not-null="true"/>
<column name="OCHCOSC" not-null="true"/>
</many-to-one>
в файл отображения Orderline.
Теперь, если я запускаю свое тестовое приложение, заказ загружается должным образом, но строки заказа не загружаются.
Я получаю {Nhibernate.adoexception} = {"Не удалось инициализировать коллекцию: ...}Я попытался исследовать и заметил, что сгенерированный запрос для извлечения рядов неправильно. Это SQL:
SELECT
orderlines0_.OCLORDN as OCLORDN1_,
orderlines0_.OCLAMND as OCLAMND1_,
orderlines0_.OCLCOSC as OCLCOSC1_,
orderlines0_.OCLLINN as OCLLINN1_,
orderlines0_.OCLSSEQ as OCLSSEQ1_,
orderlines0_.OCLORDN as OCLORDN13_0_,
orderlines0_.OCLAMND as OCLAMND13_0_,
orderlines0_.OCLCOSC as OCLCOSC13_0_,
orderlines0_.OCLLINN as OCLLINN13_0_,
orderlines0_.OCLSSEQ as OCLSSEQ13_0_,
orderlines0_.OCLITMN as OCLITMN13_0_,
orderlines0_.OCLQTYP as OCLQTYP13_0_,
orderlines0_.OCHORDN as OCHORDN13_0_,
orderlines0_.OCHAMND as OCHAMND13_0_,
orderlines0_.OCHCOSC as OCHCOSC13_0_
FROM OCSALIN orderlines0_
WHERE
orderlines0_.OCLORDN=?
and orderlines0_.OCLAMND=?
and orderlines0_.OCLCOSC=?
Как вы можете заметить, последние 3 поля Select (с префиксом OCH вместо OCL) не являются членами таблицы Ocsalin; Они являются ключом Ocsaorh.
После 1 дня, потраченных на чтение документации и примеров, я не могу понять, что я делаю неправильно.
Есть ли там кто -нибудь, кто может попытаться помочь?
Решение
Это ожидаемое поведение. Вы определяете иностранные ключи в своем картировании. Таким образом, столбцы должны существовать в объекте, который вы определяете.
Я думаю, ты хочешь это
<many-to-one name="Order" class="Order" lazy="proxy">
<column name="OCLORDN" not-null="true"/>
<column name="OCLAMND" not-null="true"/>
<column name="OCLCOSC" not-null="true"/>
</many-to-one>