117 votes

Entity framework boucle de référencement autodétectée

J'ai une erreur étrange. Je suis en train d'expérimenter avec un Web API .NET 4.5, Entity Framework et MS SQL Server. J'ai déjà créé la base de données et configuré les clés primaires et étrangères correctes ainsi que les relations.

J'ai créé un modèle .edmx et importé deux tables : Employee et Department. Un département peut avoir plusieurs employés et cette relation existe. J'ai créé un nouveau contrôleur appelé EmployeeController en utilisant les options de génération de code pour créer un contrôleur API avec des actions de lecture/écriture en utilisant Entity Framework. Dans l'assistant, j'ai sélectionné Employee comme modèle et l'entité correcte pour le contexte de données.

La méthode qui est créée ressemble à ceci :

public IEnumerable GetEmployees()
{
    var employees = db.Employees.Include(e => e.Department);
    return employees.AsEnumerable();
}

Quand j'appelle mon API via /api/Employee, j'obtiens cette erreur :

Le type 'ObjectContent`1' n'a pas réussi à sérialiser le corps de réponse pour le type de contenu 'application/json; ...System.InvalidOperationException","StackTrace":null,"InnerException":{"Message":"Une erreur s'est produite.","ExceptionMessage":"Détection de boucle auto-référente avec le type 'System.Data.Entity.DynamicProxies.Employee_5D80AD978BC68A1D8BD675852F94E8B550F4CB150ADB8649E8998B7F95422552'. Chemin '[0].Department.Employees'.","ExceptionType":"Newtonsoft.Json.JsonSerializationException","StackTrace":" ...

Pourquoi y a-t-il une auto-référence [0].Department.Employees? Cela n'a pas beaucoup de sens. Je m'attendrais à ce que cela se produise si j'avais des références circulaires dans ma base de données mais c'est un exemple très simple. Qu'est-ce qui pourrait mal se passer?

0voto

sobelito Points 135

Je pourrais également envisager d'ajouter des échantillons explicites pour chaque contrôleur/action, comme cela est bien expliqué ici :

http://blogs.msdn.com/b/yaohuang1/archive/2012/10/13/asp-net-web-api-help-page-part-2-providing-custom-samples-on-the-help-page.aspx

c'est-à-dire : config.SetActualResponseType(typeof(SomeType), "Values", "Get");

0voto

Auto-référence à titre d'exemple

public class Employee {
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public int ManagerId { get; set; }
    public virtual Employee Manager { get; set; }

    public virtual ICollection Employees { get; set; }

    public Employee() {
        Employees = new HashSet();
    }
}

HasMany(e => e.Employees)
    .WithRequired(e => e.Manager)
    .HasForeignKey(e => e.ManagerId)
    .WillCascadeOnDelete(false);

0voto

Eric Conklin Points 57

Je sais que c'est une ancienne question mais voici la solution que j'ai trouvée pour un problème de codage très similaire dans mon propre code :

var response = ApiDB.Persons.Include(y => y.JobTitle).Include(b => b.Discipline).Include(b => b.Team).Include(b => b.Site).OrderBy(d => d.DisplayName).ToArray();
        foreach (var person in response)
        {
            person.JobTitle = new JobTitle()
            {
                JobTitle_ID = person.JobTitle.JobTitle_ID,
                JobTitleName = person.JobTitle.JobTitleName,
                PatientInteraction = person.JobTitle.PatientInteraction,
                Active = person.JobTitle.Active,
                IsClinical = person.JobTitle.IsClinical
            };
        }

Étant donné que l'objet person contient tout de la table person et que l'objet job title contient une liste de personnes avec ce titre de poste, la base de données a continué de se référencer elle-même. Je pensais que désactiver la création de proxy et le chargement paresseux réglerait le problème, mais malheureusement ça n'a pas fonctionné.

Pour ceux qui ne peuvent pas le faire, essayez la solution ci-dessus. Créer explicitement un nouvel objet pour chaque objet qui se référence à lui-même, mais exclure la liste d'objets ou l'objet qui renvoie à l'entité précédente résoudra le problème, car désactiver le chargement paresseux ne semble pas fonctionner pour moi.

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