nhibernate / fluenthibernate бросает исключение StackOverflowException - PullRequest
3 голосов
/ 19 мая 2010

В своем проекте я использую NHibernate / FluentNHibernate и работаю с двумя сущностями, контрактами и сервисами.

Это мой тип контракта:

[Serializable]
public partial class TTLCContract
{
    public virtual long? Id { get; set; }
    // other properties here
    public virtual Iesi.Collections.Generic.ISet<TTLCService> Services { get; set; }

    // implementation of Equals
    // and GetHashCode here
}

и это мой тип обслуживания:

[Serializable]
public partial class TTLCService
{
    public virtual long? Id { get; set; }
    // other properties here
    public virtual Activity.Models.TTLCContract Contract { get; set; }

    // implementation of Equals
    // and GetHashCode here
}

Хорошо, так что, как вы можете видеть, я хочу, чтобы у моего объекта контракта было много сервисов, и у каждой Сервиса должна быть ссылка на родительский контракт.

Я использую FluentNhibernate. Итак, мой файл сопоставлений выглядит следующим образом:

public TTLCContractMapping()
{
    Table("tab_tlc_contracts");
    Id(x => x.Id, "tlc_contract_id");
    HasMany(x => x.Services)
            .Inverse()
            .Cascade.All()
            .KeyColumn("tlc_contract_id")
            .AsSet();
}

и

public TTLCServiceMapping()
{
     Table("tab_tlc_services");

     Id(x => x.Id, "tlc_service_id");
     References(x => x.Contract)
         .Not.Nullable()
         .Column("tlc_contract_id");
}

и тут возникает моя проблема: если я получаю список всех контрактов в БД, это работает. если я получу список всех услуг в данном контракте, я получу StackOverflowException ....

Видите ли вы что-то не так с тем, что я написал? Я сделал какую-нибудь ошибку?

Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

О да, я упустил сказать ... глядя на трассировку стека, я вижу, что система загружает все службы, а затем снова загружает контракты, связанные с этими службами.

У меня больше нет ни необходимого опыта, ни идей, чтобы понять, что происходит ... поэтому любая помощь будет действительно очень полезной!

Заранее спасибо, Ура, Джанлука.

Ответы [ 2 ]

1 голос
/ 20 мая 2010

Оказывается, что оба класса (TTLCContract и TTLCService) имеют настроенную функцию GetHashCode ().

Ну, мне почти стыдно продолжать объяснение ...

Функция TTHContract GetHashCode () вызывала GetHashCode своих собственных полей - и это правильно. Хотя одним из этих полей было «Сервис», следовательно, был вызов, такой как Service.GetHashCode (). Эта последняя функция была построена по тому же принципу: она вызывала функцию GetHashCode () для каждого из своих внутренних полей. И одним из них является контракт.

Итак, Contract.GetHashCode () вызывал Service.GetHashCode (), а Service.GetHashCode () вызывал Contract.GetHashCode (). Этот цикл был причиной исключения StackOverflowException.

На самом деле ситуация была несколько более сложной, чем та, которую я только что описал: у Контракта и Сервиса действительно много дочерних объектов, и у меня была та же проблема со многими из них.

Наш набор тестов был переписан, чтобы проверить и эти возможности.

0 голосов
/ 20 мая 2010

Похоже, что у вас может быть круговая ссылка. Я имею в виду, что вы загружаете сервисы, которые inturn загружает контракты, которые затем загружают сервисы, и мы снова идем ...

Я не уверен в свободном синтаксисе nhibernate, но посмотрите на ленивую загрузку как сервисов, так и контрактов, чтобы вы не получили этот каскадный эффект.

...