Reputation: 109
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
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
Reputation: 7800
you should use:
Attach is used to repopulate a context with an entity that is known to already exist in the database
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