Note that there are some explanatory texts on larger screens.

plurals
  1. POEF4.1 : How to deal with items being added to an Object's collection
    text
    copied!<p>I'm using EF4.1 for the first time (so be patient with me) but I just cant get to grips with how I can add new items to a sub collection of an object and then save the object.</p> <p>For example, with the classes below, I can initially save the TravelTicket (containing multiple People) into my database, but as soon as I add a new person and then try to save the TravelTicket again I get:</p> <p>An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.</p> <p>Can anyone help?</p> <pre><code>public class TravelTicket { public int Id { get; set; } public string Destination { get; set; } public virtual List&lt;Person&gt; Members { get; set; } } public class Person { public int Id { get; set; } public string Name{ get; set; } } </code></pre> <p><strong>EDITED: All relevant code added as requested:</strong></p> <p>Domain Models:</p> <pre><code>public class TravelTicket { public int Id { get; set; } public string Destination { get; set; } public virtual ICollection&lt;Person&gt; Members { get; set; } } public class Person { public int Id { get; set; } public string Name { get; set; } } </code></pre> <p>The DB Context:</p> <pre><code>public class TicketContext : DbContext { public TicketContext() : base("TicketStore") { } public DbSet&lt;TravelTicket&gt; TravelTickets { get; set; } public DbSet&lt;Person&gt; People { get; set; } } </code></pre> <p>The Repository (relevant methods only):</p> <pre><code>public class TicketRepository : ITicketRepository { TicketContext context = new TicketContext(); public void InsertOrUpdate(TravelTicket quoteContainer) { if (quoteContainer.Id == default(int)) { // New entity context.TravelTickets.Add(quoteContainer); } else { // Existing entity context.Entry(quoteContainer).State = EntityState.Modified; } } public void Save() { try { context.SaveChanges(); } catch (DbEntityValidationException dbEx) { foreach (var validationErrors in dbEx.EntityValidationErrors) { foreach (var validationError in validationErrors.ValidationErrors) { Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage); } } } } } public interface ITicketRepository { void InsertOrUpdate(TravelTicket travelTicket); void Save(); } </code></pre> <p>The consuming (example) MVC Controller code:</p> <pre><code>public class TicketSaleController : Controller { private readonly ITicketRepository ticketRepository; public TicketSaleController() : this(new TicketRepository()) { } public TicketSaleController(ITicketRepository ticketRepository) { this.ticketRepository = ticketRepository; } public ActionResult Index() { TravelTicket ticket = new TravelTicket(); ticket.Destination = "USA"; List&lt;Person&gt; travellers = new List&lt;Person&gt;(); travellers.Add(new Person { Name = "Tom" }); travellers.Add(new Person { Name = "Dick" }); travellers.Add(new Person { Name = "Harry" }); ticket.Members = travellers; ticketRepository.InsertOrUpdate(ticket); ticketRepository.Save(); Session["Ticket"] = ticket; return RedirectToAction("Next"); } public ActionResult Next() { TravelTicket ticket = (TravelTicket)Session["Ticket"]; ticket.Members.Add(new Person { Name = "Peter" }); ticket.Members.Add(new Person { Name = "Paul" }); ticketRepository.InsertOrUpdate(ticket); ticketRepository.Save(); return View(); } } </code></pre> <p>The call "ticketRepository.InsertOrUpdate(ticket);" on the "Next" method causes the exception:</p> <p><strong>An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.</strong></p> <p>FURTHER EDIT: If I pull the object back from the database after its been saved instead of pulling the object from the session, adding the 2 new persons works OK:</p> <p>Works: TravelTicket ticket = ticketRepository.Find(ticketId); ticket.Members.Add(new Person { Name = "Peter" }); ticket.Members.Add(new Person { Name = "Paul" }); ticketRepository.InsertOrUpdate(ticket); ticketRepository.Save();</p> <p>Doesn't Work: TravelTicket ticket = (TravelTicket)Session["Ticket"]; ticket.Members.Add(new Person { Name = "Peter" }); ticket.Members.Add(new Person { Name = "Paul" }); ticketRepository.InsertOrUpdate(ticket); ticketRepository.Save();</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload