Я пишу приложение, которое включает NHibernate.
Время загрузки и все в порядке, по сравнению с моей первоначальной конфигурацией. Тем не менее, я пытаюсь выполнить стресс-тест для более худшего сценария приложения. Этот стресс-тест существенно увеличил количество объектов, и теперь я сохраняю 3 класса: 2400 пересечений, 9600 зон и 5000 транспортных средств.
Моя проблема, с которой я сталкиваюсь, - попытка сохранить элементы в базе данных в первый раз. Я создаю все элементы, а затем пытаюсь сохранить их с помощью:
using (var tx = session.BeginTransaction())
{
foreach (Vehicle veh in Program.data.Vehicles.list)
{
session.Save(veh);
}
// Commit transactions
tx.Commit();
}
Однако я продолжаю натыкаться на:
System.StackOverflowException не обработан
Сообщение: необработанное исключение типа «System.StackOverflowException» произошло в System.Data.dll
Я попытался добавить счетчик для вызова Flush каждые 2 итерации цикла. Проблема в том, что Транспортное средство содержит список Зон, а Зона содержит список Транспортных Средств. Так уж получилось, что у каждого автомобиля есть список каждой зоны и наоборот. Так называется первый сеанс. Спасение - это не только сохранение первого транспортного средства, но и постановка в очередь сохранения каждой зоны, что, в свою очередь, сохраняет все транспортные средства.
У меня в списке Зон в Транспортном средстве установлено значение inverse = false; поэтому он сохраняет все зоны, которые есть в списке транспортных средств, если они не существуют.
Есть ли какой-нибудь способ сказать NHibernate о том, что изменения будут происходить так часто, чтобы я не нажимал исключение StackOverflowException? Я попытался добавить счетчик для очистки сеанса каждые 10 сохранений, но я столкнулся с исключением переполнения, прежде чем он достигнет этого. Когда он сохраняет первое транспортное средство, он сохраняет каждую зону. Поскольку каждая зона содержит каждое транспортное средство, оно спасает каждое транспортное средство. Я никогда не ударил флеш, пока не получил исключение переполнения.
Мне бы очень хотелось иметь возможность просто вызвать функцию сохранения на транспортном средстве, и она каскадно сохранит данные в Зоне. Это избавит меня от необходимости многократно повторять список зон, а затем снова ретушировать зону, когда я сохраню автомобиль.
Есть идеи?
EDIT
Кажется, он задыхается от tx.Commit (). Любая помощь в решении этой проблемы будет принята с благодарностью.
EDIT
Размещение отображений в соответствии с запросом. Я вырезал некоторые из избыточных свойств и сопоставляемых вещей и просто сохранил 3 списка для основных классов.
Транспортные средства и перекрестки являются производными от устройства и отображаются следующим образом:
<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`">
<joined-subclass name="EMTRAC.Intersections.Intersection, 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="all-delete-orphan" access="field" fetch="join" inverse="false">
<key>
<column name="Zone_PK" />
</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>
<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 на стороне Транспортного средства, чтобы, надеюсь, все они были сопоставлены через Транспортное средство, но не уверен на 100%, правильно ли это сопоставлено.