l’object quadro non può essere referenziato da più istanze di IEntityChangeTracker. aggiungendo oggetti correlati all’ quadro in Entity Framework 4.1

Sto cercando di salvare i dettagli dei dipendenti, che hanno riferimenti con City. Ma ogni volta che provo a salvare il mio contatto, che viene convalidato, ottengo l’eccezione “ADO.Net Entity Framework Un object quadro non può essere referenziato da più istanze di IEntityChangeTracker”

Avevo letto così tanti post, ma ancora non ottenevo l’idea esatta di cosa fare … il mio codice di clic del pulsante Salva è riportato di seguito

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

e il codice di servizio per i dipendenti

 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"; } 

Perché queste due linee …

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

… non prendere un parametro nel costruttore, credo che tu crei un contesto all’interno delle classi. Quando carichi la city1

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

… allega la city1 al contesto in CityService . Successivamente aggiungi una city1 come riferimento al nuovo Employee e1 e aggiungi e1 includendo questo riferimento a city1 nel contesto in EmployeeService . Di conseguenza hai city1 collegato a due diversi contesti, che è ciò di cui si lamenta l’eccezione.

È ansible risolvere questo problema creando un contesto al di fuori delle classi di servizio e iniettando e utilizzandolo in entrambi i servizi:

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

Le tue classi di servizio assomigliano un po ‘ai repository responsabili solo di un singolo tipo di quadro. In tal caso avrai sempre problemi non appena saranno coinvolte le relazioni tra le entity framework quando utilizzi contesti separati per i servizi.

È anche ansible creare un singolo servizio responsabile di un insieme di quadro strettamente correlate, come un EmployeeCityService (che ha un unico contesto) e debind l’intera operazione nel metodo Button1_Click a un metodo di questo servizio.

I passaggi per la riproduzione possono essere semplificati a questo:

 var contextOne = new EntityContext(); var contextTwo = new EntityContext(); var user = contexOne.Users.FirstOrDefault(); var group = new Group(); group.User = user; contextTwo.Groups.Add(group); contextTwo.SaveChanges(); 

Codice senza errori:

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

Questo è un thread vecchio, ma un’altra soluzione, che preferisco, è solo aggiornare il cityId e non assegnare il modello del buco City to Employee … per farlo il Dipendente dovrebbe apparire come:

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

Quindi è sufficiente assegnare:

 e1.CityId=city1.ID; 

Ho avuto lo stesso problema, ma il mio problema con la soluzione di @ Slauma (sebbene eccellente in certi casi) è che raccomando di passare il contesto al servizio che implica che il contesto sia disponibile dal mio controller. Forza anche l’accoppiamento stretto tra il mio controller e i livelli di servizio.

Uso Dependency Injection per iniettare i livelli di servizio / repository nel controller e, in quanto tale, non hanno accesso al contesto dal controller.

La mia soluzione era che i livelli servizio / repository usassero la stessa istanza del contesto: Singleton.

Contesto Classe Singleton:

Riferimento: http://msdn.microsoft.com/en-us/library/ff650316.aspx
e http://csharpindepth.com/Articles/General/Singleton.aspx

 public sealed class MyModelDbContextSingleton { private static readonly MyModelDbContext instance = new MyModelDbContext(); static MyModelDbContextSingleton() { } private MyModelDbContextSingleton() { } public static MyModelDbContext Instance { get { return instance; } } } 

Classe di deposito:

 public class ProjectRepository : IProjectRepository { MyModelDbContext context = MyModelDbContextSingleton.Instance; 

Esistono altre soluzioni come l’istanziazione del contesto una volta e il passaggio nei costruttori dei livelli del servizio / repository o un altro che ho letto a proposito dell’implementazione del modello Unità di lavoro. Sono sicuro che ci sono più …

In alternativa all’iniezione e Singleton, anche peggiore, puoi chiamare il metodo Detach prima di Aggiungi.

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

EntityFramework 4: cs.Detach(city1);

C’è ancora un altro modo, nel caso in cui non è necessario il primo object DBContext. Basta avvolgerlo con l’ utilizzo della parola chiave:

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

Nel mio caso, stavo usando l’ASP.NET Identity Framework. Avevo utilizzato il metodo incorporato UserManager.FindByNameAsync per recuperare un’ quadro ApplicationUser . Ho quindi provato a fare riferimento a questa quadro su un’entity framework appena creata su un diverso DbContext . Ciò ha comportato l’eccezione che hai visto originariamente.

Ho risolto questo problema creando una nuova quadro ApplicationUser con solo l’ Id dal metodo UserManager e facendo riferimento a tale nuova quadro.

Ho avuto lo stesso problema e ho potuto risolvere creando una nuova istanza dell’object che stavo cercando di aggiornare. Poi ho passato quell’object al mio repository.

Utilizzare lo stesso object DBContext per tutta la transazione.

Fonte di errore:

 ApplicationUser user = await UserManager.FindByIdAsync(User.Identity.Name); ApplicationDbContext db = new ApplicationDbContent(); db.Users.Uploads.Add(new MyUpload{FileName="newfile.png"}); await db.SavechangesAsync();/ZZZZZZZ 

Spero che qualcuno salvi un po ‘di tempo prezioso