48 votes

EF 4.1 - le Premier Code JSON de Référence Circulaire de la Sérialisation d'Erreur

Je suis une une Référence Circulaire de la Sérialisation d'Erreur bien que, à ma connaissance, je n'ai pas toutes les références circulaires. Je suis de la récupération d'un ensemble de Commandes à partir de la base de données et de les envoyer au client sous forme de JSON. Tout le code est indiqué ci-dessous.

C'est le message d'erreur:

Erreur

Une référence circulaire a été détecté lors de la sérialisation d'un objet de type 'System.Data.Entity.DynamicProxies.Order_83CECF2AA4DE38232F9077D4B26941ab96bc61230419ea8ac42c9100e6072812'. Description: Une exception non gérée s'est produite pendant l'exécution de la demande web actuelle. Veuillez passer en revue les trace de la pile pour plus d'informations sur l'erreur et où il trouve son origine dans le code.

Détails De L'Exception: Système.InvalidOperationException: Un référence circulaire a été détectée pendant l' la sérialisation d'un objet de type 'System.Data.Entity.DynamicProxies.Order_83CECF2AA4DE38232F9077D4B26941ab96bc61230419ea8ac42c9100e6072812'.

Source De L'Erreur:

Une exception non gérée s'est généré au cours de l'exécution de la demande web. Les informations concernant les origine et l'emplacement de l'exception peut être identifié à l'aide de l'exception trace de la pile ci-dessous.

Mes classes sont comme suit:

Afin

public class Order
{
    [Key]
    public int OrderId { get; set; }

    public int PatientId { get; set; }
    public virtual Patient Patient { get; set; }

    public int CertificationPeriodId { get; set; }
    public virtual CertificationPeriod CertificationPeriod { get; set; }

    public int AgencyId { get; set; }
    public virtual Agency Agency { get; set; }

    public int PrimaryDiagnosisId { get; set; }
    public virtual Diagnosis PrimaryDiagnosis { get; set; }

    public int ApprovalStatusId { get; set; }
    public virtual OrderApprovalStatus ApprovalStatus { get; set; }

    public int ApproverId { get; set; }
    public virtual User Approver { get; set; }

    public int SubmitterId { get; set; }
    public virtual User Submitter { get; set; }

    public DateTime ApprovalDate { get; set; }

    public DateTime SubmittedDate { get; set; }
    public Boolean IsDeprecated { get; set; }
}

Patient

public class Patient
{
    [Key]
    public int PatientId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string MiddleInitial { get; set; }
    public bool IsMale;
    public DateTime DateOfBirth { get; set; }

    public int PatientAddressId { get; set; }
    public Address PatientAddress { get; set; }

    public bool IsDeprecated { get; set; }
}

Période De Certification

public class CertificationPeriod
{
    [Key]
    public int CertificationPeriodId { get; set; }
    public DateTime startDate { get; set; }
    public DateTime endDate { get; set; }
    public bool isDeprecated { get; set; }
}

Agence

public class Agency
{
    [Key]
    public int AgencyId { get; set; }
    public string Name { get; set; }

    public int PatientAddressId { get; set; }
    public virtual Address Address { get; set; }
}

Diagnostic

public class Diagnosis
{
    [Key]
    public int DiagnosisId { get; set; }
    public string Icd9Code { get; set; }
    public string Description { get; set; }
    public DateTime DateOfDiagnosis { get; set; }
    public string Onset { get; set; }
    public string Details { get; set; }
}

OrderApprovalStatus

public class OrderApprovalStatus
{
    [Key]
    public int OrderApprovalStatusId { get; set; }
    public string Status { get; set; }
}

L'utilisateur

public class User
{
    [Key]
    public int UserId { get; set; }
    public string Login { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string NPI { get; set; }
    public string Email { get; set; }

}

NOTE: CLASSE D'ADRESSE EST UNE NOUVELLE ADDITION AU MONTAGE

Adresse

public class Address
{
    [Key]
    public int AddressId { get; set; }
    public string StreetAddress { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
    public string Phone { get; set; }
    public string Title { get; set; }
    public string Label { get; set; }
}

Le code qui exécute la sérialisation est ici:

Extrait de OrderController

    public ActionResult GetAll()
    {
        return Json(ppEFContext.Orders, JsonRequestBehavior.AllowGet);
    }

Merci

50voto

Slauma Points 76561

Vous pouvez essayer de supprimer l' virtual mot clé de toutes les propriétés de navigation de désactiver le chargement différé et la création de proxy puis utilisez avide de chargement au lieu de charger l'objet graphique explicitement:

public ActionResult GetAll()
{
    return Json(ppEFContext.Orders
                           .Include(o => o.Patient)
                           .Include(o => o.Patient.PatientAddress)
                           .Include(o => o.CertificationPeriod)
                           .Include(o => o.Agency)
                           .Include(o => o.Agency.Address)
                           .Include(o => o.PrimaryDiagnosis)
                           .Include(o => o.ApprovalStatus)
                           .Include(o => o.Approver)
                           .Include(o => o.Submitter),
        JsonRequestBehavior.AllowGet);
}

Se référant à votre post précédent , il ressemble à votre application n'est pas en s'appuyant sur le chargement paresseux de toute façon parce que vous avez mis en place il y a le virtuel propriétés de charger l'objet graphique paresseusement, ce qui pourrait causer maintenant la sérialisation de la difficulté.

Modifier

Il n'est pas nécessaire de retirer l' virtual mot-clé dans les propriétés de navigation (ce qui en ferait le chargement paresseux totalement impossible pour le modèle). Il suffit de désactiver la création de proxy (qui désactive le chargement paresseux) pour les cas spécifiques où les procurations sont troublantes, comme la sérialisation:

ppEFContext.Configuration.ProxyCreationEnabled = false;

Ceci désactive la création de proxy uniquement pour le contexte spécifique de l'instance ppEFContext.

(Je viens de le voir, @WillC déjà mentionné ici. Upvote pour ce de le modifier à sa réponse.)

44voto

WillC Points 424

Quand vous savez que vous avez besoin de sérialiser à partir d'un contexte particulier, vous pouvez désactiver la création de proxy pour cette requête particulière, comme ci-dessous. Cela a fonctionné pour moi et c'était mieux que de réviser mes classes de modèle.

using (var context = new MeContext())
{
    context.Configuration.ProxyCreationEnabled = false;
    return context.cars.Where(w => w.Brand == "Ferrari")
}

Nous espérons que cette sérialisation bug sera corrigé bientôt (mais apparemment pas jusqu'à l'après-EF5 selon l'ADO.net de l'équipe).

10voto

Christoph Points 4662

Le problème, c'est que vous êtes fait de la sérialisation d'un entity framework généré objet proxy. Malheureusement, cela a des problèmes lorsqu'il est utilisé avec le sérialiseur JSON. Vous pourriez envisager de faire un plan de votre entités spéciales simples classes POCO pour l'amour de JSON de compatibilité.

8voto

bdparrish Points 1476

Il y a un attribut à ajouter à Entity Framework objets

[ScriptIgnore]

Cela rend le code effectuent pas de références Circulaires.

7voto

John Bubriski Points 5789

Je pense qu'ils ont corrigé cela dans la dernière version.

Découvrez les aider docs sous la section "la Sérialisation et la Désérialisation JSON -> la Sérialisation et la Préservation des Références d'Objet".

Définissez ce paramètre lors de l'initialisation de la JSON.Net Sérialiseur:

PreserveReferencesHandling = PreserveReferencesHandling.Objects;

Donc, un exemple serait celui-ci:

var serializerSettings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects };

string json = JsonConvert.SerializeObject(people, Formatting.Indented, serializerSettings);

J'ai vérifié que cela fonctionne avec mon premier code de la solution, et une référence circulaire dans les propriétés de navigation. Si vous regardez la résultante JSON, il devrait avoir "$id" et "$ref" propriétés de partout.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X