0

I'm using Web API 2 and Entity Framework 6 and Identity 2

I have product model which relates to an ApplicationUser model, where I create Product, I get an error:

Additional information: An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

My model:

public class Product {
    public int id { get; set; }
    public string url { get; set; }
    public string name {get;set}
    public ApplicationUser user { get; set; }
}

My create code:

public IHttpActionResult PostProduct(Product product) {
    ApplicationUserManager userManager = new ApplicationUserManager(new UserStore<ApplicationUser>(new ApplicationDbContext()));

    product.user = userManager.FindById(User.Identity.GetUserId());

    if (!ModelState.IsValid) {
        return BadRequest(ModelState);
    }

    db.Products.Add(product);
    db.SaveChanges();

    return CreatedAtRoute("DefaultApi", new { id = product.id }, product);
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Mo3in
  • 369
  • 1
  • 7
  • 19
  • what dbcontext does "db" refer to? Looks like you have one context bringing back (and tracking) a user and adding that user as a property to an object on a different context (which will want to track it as well) – iandayman Mar 01 '15 at 21:16
  • i'm using one context for two model, my context is ApplicationDbContext. and userManager.FindById(User.Identity.GetUserId()) is not null – Mo3in Mar 01 '15 at 21:22
  • Does `product` have a primitive user id property? If so, use that to establish the association. – Gert Arnold Mar 01 '15 at 21:51

1 Answers1

0

What dbcontext does "db" refer to?

I would guess that you probably have more than one dbcontext and you are trying to retrieve data from one and persist it on another.

Maybe you can change the code to create just one dbcontext per http request and reuse that context during your http post request.

Maybe change:

ApplicationUserManager userManager = new ApplicationUserManager(new UserStore<ApplicationUser>(new ApplicationDbContext()));

to:

ApplicationUserManager userManager = new ApplicationUserManager(new UserStore<ApplicationUser>(db));

This will let you save your product but you should avoid sending back an EF object, or at least switch off lazy loading.

To clarify a bit, don't send product back in the return as it contains properties which are EF proxies for lazy loading. This will cause at best, a lot more data than you want going back when you serialise the product object and at worst - the error you describe in the comments.

iandayman
  • 4,357
  • 31
  • 38
  • hi, now my error is: `{"Message":"An error has occurred.","ExceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.","ExceptionType":"System.InvalidOperationException","StackTrace":null,"InnerException":{"Message":"An error has occurred.","ExceptionMessage":"Self referencing loop detected with type 'Khonok.Models.Audio'. Path 'user.audios'.","ExceptionType":"Newtonsoft.Json.JsonSerializationException","StackTrace":" at ...` – Mo3in Mar 01 '15 at 21:36
  • 1
    i wouldn't recommend serialising and sending an entityframework object over the wire as you can end up sending the entire object graph and you will get errors like that. Perhaps use viewmodels / dto – iandayman Mar 01 '15 at 21:44