Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AsNoTracking duplicating entities

sorry for my poor english - I'm using EF 5 (Code First) in an WPF (.net 4.5) application. Each window has its own context.

I have a model like this (code omitted for brevity):

public class Car
{
  public string Model { get; set; }  
  public int BrandId { get; set; }  
  public virtual Brand Brand { get; set; }
}

I use comboboxes to allow the user to associate a Brand to a Car. The problem is, every time I save a Car, a new, duplicated Brand are saved too. This happens because I load the combobox with AsNoTracking().

Now, I load the combobox with AsNoTracking() because I was having trouble loading changes on the Brand table made in other DbContext instances (using myContext.Set<Brand>().Load()).

So my question is, how to resolve this? If there is another way to force reload of a collection (without using AsNoTracking), it would be nice. Even nicer would be to be able to inform EF that the AsNoTracking loaded entities are not new.

EDIT 1: @Mark: Thanks, attaching the entity to the context did the trick. But I use a generic base class that does the validation and save the data for all my forms so manually attaching the entities are not very practical... based on your suggestion I ended up doing this, after adding the Car entity and before saving it:

var entities = (((IObjectContextAdapter)ctx).ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added));

foreach (var item in entities)
{
    if ((item.Entity as EntityBase).Id > 0)
    {
        item.ObjectStateManager.ChangeObjectState(item.Entity, EntityState.Unchanged);
    }
}

(all my entites inherit from EntityBase and all my keys are database-generated). This worked fine but i would like a second opinion... is this good or there is an easier way to do it?

like image 349
user1526627 Avatar asked Oct 28 '25 17:10

user1526627


1 Answers

What's happening is that your context isn't aware of the Brand that's attached to the Car, so it's creating a new one to match your foreign key. You should attach the brand to the context before saving:

context.Brands.Attach(brand);

You can reload the individual Brand prior to saving by reloading it individually:

db.Entry(brand).Reload();

If you're not wanting to actually persist any changes to Brand when you're saving a Car, you can tell the context that the Brand has not been changed, and prevent updates.

context.Entry(brand).State = EntityState.Unchanged;
like image 131
Mark Oreta Avatar answered Oct 31 '25 12:10

Mark Oreta