Хорошо, я наконец понял, что я делаю не так. Моя окончательная версия сопоставлений была:
Автомобиль:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class xmlns="urn:nhibernate-mapping-2.2" name="EMTRAC.Devices.Device, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Device`">
<id name="PK" type="System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="PK" />
<generator class="identity" />
</id>
<version name="LastModifiedOn" column="LastModifiedOn" type="timestamp" access="field.pascalcase-underscore" />
<joined-subclass name="EMTRAC.Vehicles.Vehicle, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<key>
<column name="Device_id" />
</key>
<component name="Zones" access="property">
<bag name="_list" cascade="save-update" access="field" table="VehicleZones" inverse="true">
<key>
<column name="veh_id" not-null="true"/>
</key>
<many-to-many class="EMTRAC.Zones.Zone, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</bag>
</component>
<property name="ID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="ID" />
</property>
</joined-subclass>
</class>
</hibernate-mapping>
Зона:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class xmlns="urn:nhibernate-mapping-2.2" name="EMTRAC.Zones.Zone, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Zone`">
<id name="ID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="PK"/>
<generator class="identity" />
</id>
<version name="LastModifiedOn" column="LastModifiedOn" type="timestamp" access="field.pascalcase-underscore" />
<property name="ID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="ID" />
</property>
<component name="Vehicles" access="property">
<bag name="_list" cascade="save-update" access="field" table="VehicleZones">
<key>
<column name="veh_id" not-null="true"/>
</key>
<many-to-many class="EMTRAC.Vehicles.Vehicle, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</bag>
</component>
</class>
</hibernate-mapping>
Они вызывали у меня все мои проблемы, когда было установлено обратное = "true" на стороне отображения зоны.
Если вы заметили, я убрал этот флажок со стороны зоны и поместил его на конце транспортного средства. Этот флаг сообщает Hibernate, какой класс отвечает за поддержание отношений. Я спас Автомобиль, а не Зону, которая вызывала ошибки, связанные с внешними ключами.
Поскольку я действительно хотел, чтобы Транспортное средство отвечало за сохранение этих отношений, мне нужно было установить обратное значение true на стороне Транспортного средства. Мне также нужно было пометить каскады как «сохранить-обновить», чтобы Транспортное средство каскадно обновляло зоны и связывало связь с Зоной. Таким образом, сохранение одного транспортного средства связывает зоны в таблице, а также сохраняет объект Zone, эффективно исправляя ошибки, с которыми я сталкивался в процессе сохранения ранее.
Теперь сохранение работает нормально. Хотя я бы порекомендовал подход к сохранению этих элементов в соответствии с:
foreach (Vehicle veh in Program.data.Vehicles.list)
{
using (ITransaction tx = session.BeginTransaction())
{
session.Save(veh);
// Commit transactions
tx.Commit();
}
}
Если в двух списках большое количество классов.
Причина этого заключается в том, что ваша транзакция будет блокировать элементы в базе данных до тех пор, пока вы не вызовете фиксацию. После вызова коммита все обновления и все, что было в очереди, фактически выполняются. Таким образом, сохранение - это просто отправка фактических транзакций в базу данных, которая будет выдана после вызова commit. Сам коммит - это место, где выполняется вся фактическая работа, и как только она вызывается, фактические элементы сохраняются в базе данных. Очевидно, вы не хотите, чтобы транзакция занимала очень длительный период времени.
В моем случае я пытался спасти 5000 автомобилей и 9600 зон. В результате получится таблица, отвечающая за хранение двух списков, содержащих 48 миллионов строк, и, следовательно, причина для создания отдельной транзакции и фиксации вызова для каждого транспортного средства. Использование этого подхода предотвращает блокировку этих элементов в течение всего срока действия этих 48 миллионов вставок и является гораздо более эффективным. Вместо этого фиксация вызывается после сохранения каждого транспортного средства, поэтому, кроме самого первого сохраненного транспортного средства (поскольку первое сохранение должно сохранять также все зоны, если они не существуют), будет выполнено только 9600 команд на сделка. Это, очевидно, намного лучше, чем 48 миллионов.
Однако я хотел бы отметить, что это не было серьезной проблемой с гораздо меньшим размером выборки. Это то, что каждый должен принять во внимание.
Надеюсь, это поможет любому, кто наткнется на это.