187 votes

l'objet entité ne peut pas être référencé par plusieurs instances de IEntityChangeTracker. lors de l'ajout d'objets connexes à l'entité dans Entity Framework 4.1

J'essaie de sauvegarder les détails de l'employé, qui a des références avec la ville. Mais chaque fois que j'essaie de sauvegarder mon contact, qui est validé, je reçois l'exception suivante "ADO.Net Entity Framework Un objet d'entité ne peut être référencé par plusieurs instances de IEntityChangeTracker"

J'ai lu de nombreux articles, mais je n'ai toujours pas trouvé l'idée exacte de ce qu'il faut faire... mon code de clic du bouton Save est donné ci-dessous

protected void Button1_Click(object sender, EventArgs e)
    {
        EmployeeService es = new EmployeeService();
        CityService cs = new CityService();

        DateTime dt = new DateTime(2008, 12, 12);
        Payroll.Entities.Employee e1 = new Payroll.Entities.Employee();

        Payroll.Entities.City city1 = cs.SelectCity(Convert.ToInt64(cmbCity.SelectedItem.Value));

        e1.Name = "Archana";
        e1.Title = "aaaa";
        e1.BirthDate = dt;
        e1.Gender = "F";
        e1.HireDate = dt;
        e1.MaritalStatus = "M";
        e1.City = city1;        

        es.AddEmpoyee(e1,city1);
    }

et Code du service des employés

public string AddEmpoyee(Payroll.Entities.Employee e1, Payroll.Entities.City c1)
        {
            Payroll_DAO1 payrollDAO = new Payroll_DAO1();
            payrollDAO.AddToEmployee(e1);  //Here I am getting Error..
            payrollDAO.SaveChanges();
            return "SUCCESS";
        }

256voto

Slauma Points 76561

Parce que ces deux lignes...

EmployeeService es = new EmployeeService();
CityService cs = new CityService();

... ne prennent pas de paramètre dans le constructeur, je suppose que vous créez un contexte dans les classes. Lorsque vous chargez les city1 ...

Payroll.Entities.City city1 = cs.SelectCity(...);

...vous attachez le city1 au contexte dans CityService . Plus tard, vous ajoutez un city1 comme référence à la nouvelle Employee e1 et ajouter e1 y compris cette référence à city1 au contexte dans EmployeeService . En conséquence, vous avez city1 attachés à deux contextes différents, ce qui est ce dont l'exception se plaint.

Vous pouvez résoudre ce problème en créant un contexte en dehors des classes de service et en l'injectant et l'utilisant dans les deux services :

EmployeeService es = new EmployeeService(context);
CityService cs = new CityService(context); // same context instance

Vos classes de service ressemblent un peu à des référentiels qui ne sont responsables que d'un seul type d'entité. Dans un tel cas, vous aurez toujours des problèmes dès que des relations entre entités sont impliquées lorsque vous utilisez des contextes séparés pour les services.

Vous pouvez également créer un service unique qui est responsable d'un ensemble d'entités étroitement liées, comme une EmployeeCityService (qui a un seul contexte) et déléguer l'ensemble de l'opération dans votre Button1_Click à une méthode de ce service.

5 votes

J'aime la façon dont tu as trouvé la solution, même si la réponse n'a pas inclus d'informations de base.

0 votes

On dirait que cela va résoudre mon problème, je n'ai juste aucune idée de comment écrire la nouvelle instance de contexte :(

13 votes

Abstraire ORM, c'est comme mettre du rouge à lèvres jaune sur un étron.

36voto

Pavel Shkleinik Points 329

Les étapes de la reproduction peuvent être simplifiées comme suit :

var contextOne = new EntityContext();
var contextTwo = new EntityContext();

var user = contextOne.Users.FirstOrDefault();

var group = new Group();
group.User = user;

contextTwo.Groups.Add(group);
contextTwo.SaveChanges();

Code sans erreur :

var context = new EntityContext();

var user = context.Users.FirstOrDefault();

var group = new Group();
group.User = user; // Be careful when you set entity properties. 
// Be sure that all objects came from the same context

context.Groups.Add(group);
context.SaveChanges();

En utilisant un seul EntityContext peut résoudre ce problème. Reportez-vous aux autres réponses pour d'autres solutions.

9voto

user3484623 Points 111

Il s'agit d'un vieux fil de discussion, mais une autre solution, que je préfère, est de simplement mettre à jour le cityId et de ne pas affecter le modèle de trou City à l'employé... pour ce faire, Employee devrait ressembler à ceci :

public class Employee{
    ...
    public int? CityId; //The ? is for allow City nullable
    public virtual City City;
}

Ensuite, il suffit d'assigner :

e1.CityId=city1.ID;

5voto

Roman O Points 312

Alternativement à l'injection et encore pire à Singleton, vous pouvez appeler Détacher avant d'ajouter.

EntityFramework 6 : ((IObjectContextAdapter)cs).ObjectContext.Detach(city1);

EntityFramework 4 : cs.Detach(city1);

Il existe encore une autre solution, au cas où vous n'auriez pas besoin du premier objet DBContext. Il suffit de l'envelopper avec en utilisant mot-clé :

Payroll.Entities.City city1;
using (CityService cs = new CityService())
{
  city1 = cs.SelectCity(Convert.ToInt64(cmbCity.SelectedItem.Value));
}

3voto

Justin Skiles Points 2885

Dans mon cas, j'utilisais l'ASP.NET Identity Framework. J'avais utilisé la fonction intégrée UserManager.FindByNameAsync pour récupérer un ApplicationUser entité. J'ai ensuite essayé de référencer cette entité sur une entité nouvellement créée sur un autre site. DbContext . Cela a donné lieu à l'exception que vous avez vue à l'origine.

J'ai résolu ce problème en créant un nouveau ApplicationUser avec seulement le Id de la UserManager et en faisant référence à cette nouvelle entité.

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