6

I'm using EF with code-first and I have models like this:

public class Product
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    public Customer Customer { get; set; }
}

public class Customer 
{
    public Customer ()
    {
        Products = new List<Product>();
    }

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }

    // more stuff snipped...

    public ICollection<Product> Products{ get; set; }
}

I am receiving a customer ID along with a list of product IDs. When the product doesn't exist in the DB, I want to add it:

    var newProduct = new Product{ Id = id, Name = "<no name yet>", Customer = customer };
    InsertProduct(newProduct);

The problem is that EF tries to cascade the changes and tries to insert a new Customer object, with the same ID as an existing one, so it fails. How do I solve this?

This is the insert method:

    public void InsertProduct(Product item)
    {
        CustomerContext.Entry(item).State = EntityState.Added;
        CustomerContext.Set<Product>().Add(item);
    }
Jan van Bloem
  • 65
  • 1
  • 5

2 Answers2

3

Taken from here.

When adding a new entity that has existing child objects (object that exists in the database), if the child objects are not tracked by EF, the child object will be re-inserted. Unless you manually attach the child object first.

Try something like the following to set the child objects state:

public void InsertProduct(Product item)
{
    // Calling this code before the context is aware of the Child
    // objects will cause the context to attach the Child objects to the     
    // context and then set the state.
    // CustomerContext.Entry(childitem).State = EntityState.Unchanged
    CustomerContext.Entry(item.ChildObject).State = EntityState.Modified;

    CustomerContext.Entry(item).State = EntityState.Added;
    CustomerContext.Set<Product>().Add(item);
}
Community
  • 1
  • 1
Paul Zahra
  • 9,522
  • 8
  • 54
  • 76
0

It is easier if you add a foreign key to the parent class:

public class Product
{
    ....

    public int CustomerId { get; set; }

    public Customer Customer { get; set; }
}

Then when you want to insert, set the foreign key instead of the navigation property:

    var newProduct = new Product
       { 
          Id = id, 
          Name = "<no name yet>", 
          CustomerId = customer.Id 
       };
   InsertProduct(newProduct);

References:

Why does Entity Framework Reinsert Existing Objects into My Database?

Making Do with Absent Foreign Keys

Colin
  • 22,328
  • 17
  • 103
  • 197