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?
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With