3 Stimmen

Nhibernate/fluenthibernate wirft eine StackOverflowException

In meinem Projekt verwende ich NHibernate/FluentNHibernate und arbeite mit zwei Entitäten, Verträgen und Dienstleistungen.

Dies ist mein Vertragstyp:

[Serializable]
public partial class TTLCContract
{
    public virtual long? Id { get; set; }
    // andere Eigenschaften hier
    public virtual Iesi.Collections.Generic.ISet Services { get; set; }

    // Implementierung von Equals
    // und GetHashCode hier
}

und das ist mein Servicetyp:

[Serializable]
public partial class TTLCService
{
    public virtual long? Id { get; set; }
    // andere Eigenschaften hier
    public virtual Activity.Models.TTLCContract Contract { get; set; }

    // Implementierung von Equals
    // und GetHashCode hier
}

Also wie Sie sehen können, möchte ich, dass mein Vertragsobjekt viele Dienstleistungen hat und dass jede Dienstleistung eine Referenz auf den übergeordneten Vertrag hat.

Ich verwende FluentNhibernate. Also sehen meine Mapping-Dateien wie folgt aus:

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();
}

und

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

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

und hier habe ich mein Problem: Wenn ich die Liste aller Verträge in der Datenbank abrufe, funktioniert es. Wenn ich jedoch die Liste aller Dienstleistungen in einem bestimmten Vertrag abrufe, erhalte ich eine StackOverflowException...

Sehen Sie irgendwelche Fehler in dem, was ich geschrieben habe? Habe ich einen Fehler gemacht?

Bitte lassen Sie mich wissen, wenn Sie weitere Informationen benötigen.

Ach ja, ich habe vergessen zu sagen... wenn ich mir den Stacktrace anschaue, sehe ich, dass das System alle Dienstleistungen lädt und dann wieder die Verträge lädt, die mit diesen Dienstleistungen zusammenhängen.

Ich habe nicht mehr genügend Erfahrung oder Ideen, um zu verstehen, was los ist... daher wäre jede Hilfe wirklich sehr sehr großartig!

Vielen Dank im Voraus, Cheers, Gianluca.

1voto

Anthares Punkte 1031

Es stellt sich heraus, dass beide Klassen (TTLCContract & TTLCService) eine angepasste GetHashCode() Funktion haben.

Nun, ich fühle mich fast beschämt, die Erklärung fortzusetzen...

TTLCContract's GetHashCode() rief die GetHashCode() seiner eigenen Felder auf - und das ist richtig. Allerdings war eines dieser Felder "Service", daher gab es einen Aufruf wie Service.GetHashCode(). Diese letztere Funktion war nach dem gleichen Prinzip aufgebaut: sie rief die GetHashCode() Funktion für jedes ihrer internen Felder auf. Und eines davon ist Contract.

Also rief Contract.GetHashCode() Service.GetHashCode() auf und Service.GetHashCode() rief Contract.GetHashCode() auf. Diese Schleife war der Grund für die StackOverflowException.

Eigentlich war die Situation etwas komplexer als die, die ich gerade beschrieben habe: Contract und Service haben tatsächlich viele Kindobjekte, und ich hatte das gleiche Problem bei vielen von ihnen.

Unser Testfall wurde nun umgeschrieben, um auch gegen diese Eventualitäten zu testen.

0voto

Nathan Fisher Punkte 7781

Es scheint, als ob ein zirkulärer Verweis vorliegen könnte. Damit meine ich, dass Sie die Dienste laden, die wiederum die Verträge laden, die dann die Dienste laden und so weiter...

Ich bin mir nicht sicher über die genaue NHibernate-Syntax, aber schauen Sie sich die Lazy Loading von sowohl Diensten als auch Verträgen an, damit Sie diesen Kaskadeneffekt vermeiden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X