Переполнение стека во время каскадного сохранения сущности nhibernate с помощью собственного генератора - PullRequest
1 голос
/ 08 февраля 2010

Я довольно новичок в Nhibernate, поэтому извиняюсь за длинное описание

Я подозреваю, что изменение структуры устаревшей БД, вероятно, является наилучшим вариантом, но я хочу попробовать и заставить NHibernate справиться с этим.

По сути, структура EndPoint имеет адрес и контакт. Конечная точка хранится в таблице с составным идентификатором (идентификатор адреса, идентификатор контакта).

У меня возникла проблема при каскадном сохранении адреса, который имеет собственный генератор идентификаторов - адреса имеют форму "ADR000234", чтобы соответствовать устаревшей структуре БД.

Генератор пользовательских идентификаторов включает запрос, и когда я сохраняю адрес как часть конечной точки, я получаю переполнение стека. При отладке курсор попадает в строку, которая оценивает запрос (var maxAddressID ..), затем возвращается к началу метода и продолжает это делать, пока не вызовет переполнение стека.

Вот мой класс генератора

public class AddressIdGenerator :  IIdentifierGenerator
{
    public object Generate(ISessionImplementor session, object obj)
    {
        var castAsSession = (ISession)session;
        var allAddresses = castAsSession.CreateQuery("select max(Code) from Address a");
        var maxAddressID = (string)allAddresses.List()[0];
        var previousNumber = int.Parse(maxAddressID.Substring(3, 6));

        return GetNewId("ADR", previousNumber);
    }

    private string GetNewId(string prefix, int number)
    {
        return prefix + (number + 1).ToString().PadLeft(6, '0');
    }
}

Вот мое сопоставление с EndPoint CLass

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
    assembly="DataClasses"
    namespace="DataClasses">
    <class name="EndPoint" table="[Addresses_Contacts]">
    <composite-id>
    <key-property name ="Address" column ="[Address ID]" type="string" />
    <key-property name ="Contact" column ="[Contact ID]" type="string"/>
    </composite-id>

    <many-to-one name="Address" class="DataClasses.Address, DataClasses" cascade="save-update"/>
    <many-to-one name="Contact" class="DataClasses.Contact, DataClasses" cascade="save-update"/>

    </class>
    </hibernate-mapping>

и отображение для адреса:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DataClasses" namespace="DataClasses">
<class name="Address" table="[Lookup Addresses]" >
<id name="Code" column="ID" type="string">
  <generator class="Nhibernate.AddressIdGenerator, Nhibernate" />
</id>
<property name="OrganisationName" column="[Name of Organisation]"/>
<property name="StreetAddress1" column="[Park/centre/estate]" />
<property name="StreetAddress2" column="[Street Name]" />
<property name="Town" column="[Town/City]" />
<property name="State" column="[Region/ State]" />
<property name="PostCode" column="[Postal/ Area Code]" />
<property name="District" column="[Local District]" />
<property name="Airport" column="[Airport code]" />
<many-to-one name="Country" class="DataClasses.Country, DataClasses" column ="[Country Code]"/>
</class>
</hibernate-mapping>

Если я попытаюсь сохранить и Адресацию самостоятельно, она работает нормально, идентификатор генерируется без проблем.

Также, если я удаляю свойства адреса и контакта из сопоставления (но не из составного идентификатора) и сохраняю адрес и контакт перед сохранением конечной точки, это тоже нормально.

Мне кажется, что когда я делаю каскадное сохранение, по какой-то причине он не может запускать другие запросы во время процесса, но вместо того, чтобы выдавать исключение, он ведет себя странно (перезапускает метод снова и снова). Я никогда не видел, чтобы метод C # делал это раньше. Я хотел бы знать, есть ли у кого-нибудь идея, как это исправить.

Ответы [ 2 ]

1 голос
/ 19 марта 2011

обновите владельца отношения в сопоставлении EndPoint xml.пожалуйста, укажите inverse = "true" во множестве к одному для адреса и контактов.спасибо

1 голос
/ 13 февраля 2010

Я думаю, что проблема заключается в том, что вы делаете nh-запрос в Генераторе и запрашиваете тип сущности, которую хотите сохранить.

Генератор вызывается не тогда, когда вы вызываете Save (), а всякий раз, когда необходимо очистить / зафиксировать данные. Теперь Save () помещает объект в очередь действий. Когда вы вызываете CreateQuery / CreateCriteria и запрашиваете результат через List () / UniqueResult (), механизм nhibernate обнаруживает, что вы сделали запрос Save () для объекта, и поэтому сначала попытается сбросить / зафиксировать объект (и, таким образом, вызвать генератор). а затем выполнить запрос и, таким образом, запустить бесконечный цикл; Логика такова, что, поскольку вы вызвали Save (), а затем запрашиваете этот тип класса, вам нужно, чтобы в результирующий набор был включен сохраненный объект.

Итак, замените ваш Nh-запрос на собственный SqlCommand (есть вероятность, что CreateSqlQuery тоже будет работать), и я думаю, что ваша проблема будет решена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...