2017-03-15 3 views
2

Ich habe viele frühere Lösungen für dieses Problem gelesen, aber keine funktionierte für mich.Selbstreferenzierungsschleife erkannt

Ich habe eine kreisförmige Beziehung zwischen Ereignis und Benutzerobjekt:

public class Event : EntityData 
{ 
    [Required] 
    [ForeignKey("Creator")] 
    public string CreatorId { get; set; } 
    public User Creator { get; set; } 

    [InverseProperty("ParticipantIn")] 
    public virtual ICollection<User> Participants { get; set; } 

    [InverseProperty("ManagerIn")] 
    public virtual ICollection<User> Managers { get; set; } 
} 

Wie Sie Ich habe drei Referenzen auf Benutzer von dieser Klasse sehen können: Ereigniserzeuger, Liste der Manager, und die Teilnehmerliste.

Die Benutzerklasse Verweise auf Ereignis enthält auch:

public class User: EntityData 
{ 
    [InverseProperty("Participants")] 
    public virtual ICollection<Event> ParticipantIn { get; set; } 

    [InverseProperty("Managers")] 
    public virtual ICollection<Event> ManagerIn { get; set; } 
} 

Nun ist das Problem, dass wenn ich versuche, ein Ereignis zu serialisiert, wie in meiner create Funktion, es sagt mir, dass es eine Selbst Referenzierung Schleife, denn wenn das Ereignis erstellt wird, füge ich es der 'ManagerIn'-Sammlung des Erstellers hinzu.

Diese Zeile verursacht Event-> Schöpfer-> ManagerIn-> Event-> Creator -> ..... LOOP

Ich versuchte alles, ich hatte auch eine Version dieses Codes mit öffentlichen virtuellen Benutzer Creator, um es gemächlich zu machen zu laden ..

Denn jetzt ist meine Lösung nicht sehr elegant, bevor das Ereignis an den Client zurückgegeben ich ausführen:

event.Creator = null; 

und

event.Managers = null; 

um eine selbstreferenzierende Schleife zu vermeiden.

Was ist der richtige Weg, um diese Art von Problem zu lösen?

Vielen Dank im Voraus, Liran!

+0

Was verwenden Sie, um es zu serialisieren? – Evk

+1

Wenn Sie XML verwenden http://stackoverflow.com/questions/5004397/is-it-possible-to-perform-serialization-with-circular-references relevant sein – Chris

+1

http://stackoverflow.com/questions/ 26434738/wie-do-you-wirklich-serialize-Kreisverweis-Objekte-mit-newtonsoft-json von Interesse für json – Chris

Antwort

0

Ich lese das ist eine Möglichkeit, dies zu tun.

Andernfalls würde ich Serialisierung zu einem anderen Objekt vorschlagen und vermeiden, Ihre Poco's zu serialisieren.

0

Da Sie die Auflistungen als virtual angeben, ist Entity Framework Lazy Laden der zugehörigen Entitäten, die Objekte mit Zirkelverweisen erstellen, mit denen der WebAPI-JSON-Serializer nicht besonders gut funktioniert. mit

MyEntities.Configuration.LazyLoadingEnabled = false; 

Sie können Lazy Loading-für die bestimmte Abfrage oder Abfragen deaktivieren oder wenn man wollte, entfernen Sie das virtual Schlüsselwort aus der Eigenschaftsdeklaration. Mit jeder dieser Optionen können Sie dann eifrig Last die damit verbundene Sammlung, wenn die Include Erweiterungsmethode erforderlich unter Verwendung von in etwa so:

MyEntities.Set<Users>() 
    .Include(u => u.ManagerIn) 
    .Include("ParticipantIn"); 

(oben zeigt beide Optionen zu Eager laden Fügen Sie verwenden)

Die Load Methode Sie können auch verwandte Entitäten explizit laden. Here ist ein Stack Overflow bei Include vs.Last

Ich habe auch etwas Ähnliches getan, was Sie angegeben haben, zur Einstellung der damit verbundene Einrichtung Sammlung auf null, das zu verhindern, dass in der Serialisierung enthalten ist. Dafür würde ich empfehlen, Ihre POCO/Entity zunächst einem DTO (Data Transfer Object) zuzuordnen, damit Sie etwas Wiederholbares einrichten und vermeiden können, SaveChanges() versehentlich im selben Kontext aufzurufen und die Beziehung zwischen Ihren Entitäten in SQL unbeabsichtigt zu entfernen. Automapper ist eine bestehende Lösung, die diese Zuordnung zu einem DTO durchführen kann, oder Sie können Ihre eigene Mapper-Dienstprogrammklasse schreiben, um sich ein wenig mehr Kontrolle zu geben.

Die letzte mögliche Option (die ich kenne) ist, die HttpConfiguration.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandinging Einstellungen so anzupassen, dass die Referenzbehandlung für alles/arrays/objects ignoriert wird.

Es hängt wirklich von Ihren Anforderungen und dem Rest des Codes. Hoffentlich führt dich einer von ihnen auf den richtigen Weg und viel Glück!

+0

Hallo Mann! Danke für die angegebene Antwort. Aber was immer ich auch mache, ich bekomme immer noch diesen Fehler. Lassen Sie mich Ihnen ein Beispiel geben. In meiner create-Event-Funktion führe ich var insert = context.Events.Add (event); welches das Ereignis hinzufügt, Dann finde ich den Benutzer, der das Ereignis mit var creator = await context.Users.FindAsync (neues Objekt [] {creatorId}) erstellt habe; ich tue dies, um creator.ManagerIn.Add (created); also wird die Veranstaltung auf seiner Liste stehen. Sobald ich das Erstellerobjekt geladen habe, enthält das eingefügte Objekt nun einen Zirkelverweis auf den Ersteller, der auf das Ereignis verweist usw. –