2010-05-19 3 views
3

В моем проекте я использую NHibernate/FluentNHibernate, и я работаю с двумя объектами, контрактами и службами.nhibernate/fluenthibernate throws StackOverflowException

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

[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 
} 

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

Я использую 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 ....

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

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

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

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

Заранее спасибо, Cheers, Gianluca.

+0

Неужели вам действительно нужен обратный? –

+0

Ну, это то, что я поставил, чтобы попытаться разобраться с этой проблемой. Как я уже сказал, у меня кончились идеи:/О, тоже .. У меня было другое исключение без него, поэтому я предполагаю, что это необходимо ... в таблице tab_services есть ссылка на контракт (следовательно, tab_tlc_services. tlc_contract_id), поэтому я думаю, что я могу быть там ... но, как я сказал ранее, я принимаю предложения от экспертов ... –

+0

Можете ли вы опубликовать полное исключение ('ex.ToString()')? –

ответ

1

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

Ну, я чувствую себя почти стыдно вести с объяснением ...

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

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

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

Наш тестовый набор теперь переписан, чтобы также протестировать их.

0

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

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

+0

Ссылки и коллекции NHibernate по умолчанию поленились, и даже если бы они не были, то идентификационная карта гарантирует, что циркулярные ссылки будут работать. –

+1

Спасибо Диего за разъяснение. Это всегда было так или только недавно изменено, чтобы быть ленивым по умолчанию? –

Смежные вопросы