Kendoha
Kendoha

Reputation: 109

Entity Framework 6 Update Many to Many without updating or loading Child

I want to Update a Record that has a many to many relationship with other records. My Problem is, that it always tries to also Update its children, which fails because the child has required fields and I only provide the ID.

I dont want to load the child-objects. I just want it to insert the Address and update the many-to-many table.

Address has an IEnumerable, that contains the ProductIDs, the other fields are empty or have the default value(ints an bools).

I get the following Error:

Property: Name Error: Please enter a Name Property: Description Error: Please enter a Description Property: Category Error: Please enter a Category

[HttpPost]
    public ActionResult ReceiveOrder(Address address)
    {
        EFDbContext context = new EFDbContext();

            context.Addresses.Add(address);
            context.SaveChanges();
            context.Dispose();
            return Json(new { success = true, responseText = "Okay" }, JsonRequestBehavior.AllowGet);
    }

Address class:

    public class Address
{
    public int AddressID { get; set; }
    public string Name { get; set; }
    public string Street { get; set; }
    public virtual List<Product> Products { get; set; }
    public bool Giftwrap { get; set; }
}

Product class

public class Product
{

    [HiddenInput(DisplayValue =false)]
    public int ProductID { get; set; }
    [Required(ErrorMessage ="Please enter a Name")]
    public string Name { get; set; }
    [DataType(DataType.MultilineText)]
    [Required(ErrorMessage = "Please enter a Description")]
    public string Description { get; set; }
    [Required(ErrorMessage = "Please enter a Price")]
    public decimal Price { get; set; }
    [Required(ErrorMessage = "Please enter a Category")]
    public string Category { get; set; }

    public byte[] ImageData { get; set; }
    public string ImageMimeType { get; set; }

    public virtual List<Address> Addresses { get; set; }
}

How do I tell EF that its only supposed to Insert Address and update the relationsship Table. I don't want to generate Overhead by loading Products first. I also dislike accessing the Products table when its not necessary.

Upvotes: 4

Views: 2564

Answers (2)

CicheR
CicheR

Reputation: 399

Note: just realizing this question is a very old one, for old Entity Framework. My answer is working for newer EF Core versions

I have a very similar situation, and I just solved it by putting state = EntityState.Unchanged for children objects:

public async Task<ActionResult<int>> Put([FromBody]NewsAlert newsAlertPut)
{

    context.NewsAlerts.Update(newsAlertPut);
    
    //To avoid saving each UserSegment, since here only the Id is provided.
    //With this [for] loop only the ManyToMany relation is updated (NewsAlertUserSegment)
    foreach (var userSegment in newsAlertPut.UserSegments)
    {
        context.Entry(userSegment).State = EntityState.Unchanged;
    }
    
    await context.SaveChangesAsync();

    return newsAlertPut.Id;
}

Upvotes: 0

tschmit007
tschmit007

Reputation: 7800

you should use:

  • Attach method (DbSet) to activate the modification tracking.

Attach is used to repopulate a context with an entity that is known to already exist in the database

  • Entry method (DbContext) to be able to set the Status of the attached entity.

You may alsa want to read Add/Attach and Entity States

for many products:

public ActionResult ReceiveOrder(Address address)
{
    EFDbContext context = new EFDbContext();

    context.Set<Addresses>().Attach(address);
    foreach(Product p in address.Products) {
        context.Set<Products>().Attach(p);
    }
    context.Entry(address).State = EntityState.Added; 

    context.SaveChanges();
    context.Dispose();
    return Json(new { success = true, responseText = "Okay" },
            JsonRequestBehavior.AllowGet);
}

Upvotes: 1

Related Questions