I'm trying to update a Customer
in my database using ASP.NET Web API and Entity Framework 5 code-first, but it's not working. My entities look like this:
public class CustomerModel
{
public int Id { get; set; }
public string Name { get; set; }
// More fields
public ICollection<CustomerTypeModel> CustomerTypes { get; set; }
}
public class CustomerTypeModel
{
public int Id { get; set; }
public string Type { get; set; }
[JsonIgnore]
public ICollection<CustomerModel> Customers { get; set; }
}
Nothing all that special. I've built a web interface where users can add a customer by supplying the name and checking one or more customer types. When hitting the submit button, the data is sent to my Web API method:
public void Put([FromBody]CustomerModel customer)
{
using (var context = new MyContext())
{
context.Customers.Attach(customer);
context.Entry(customer).State = EntityState.Modified;
context.SaveChanges();
}
}
This updates the customer fields, but the related customer types are ignored. The incoming customer
object does contain a list of CustomerTypes
it should be associated with:
[0] => { Id: 1, Type: "Finance", Customers: Null },
[1] => { Id: 2, Type: "Insurance", Customers: Null }
[2] => { Id: 3, Type: "Electronics", Customers: Null }
But instead of looking at this list and adding/removing associated entities, EF just ignores it. New associations are ignored and existing associations remain even if they should be deleted.
I had a similar problem when inserting a customer into the database, this was fixed when I adjusted the state of these entities to EntityState.Unchanged
. Naturally, I tried to apply this same magic fix in my update scenario:
public void Put([FromBody]CustomerModel customer)
{
using (var context = new MyContext())
{
foreach (var customertype in customer.CustomerTypes)
{
context.Entry(customertype).State = EntityState.Unchanged;
}
context.Customers.Attach(customer);
context.Entry(customer).State = EntityState.Modified;
context.SaveChanges();
}
}
But EF keeps displaying the same behavior.
Any ideas on how to fix this? Or should I really just do a manual clear to the list of CustomerTypes
and then manually add them?
Thanks in advance.
JP
A many-to-many relationship is defined in code by the inclusion of collection properties in each of the entities - The Categories property in the Book class, and the Books property in the Category class: public class Book. { public int BookId { get; set; }
Step 1 – Add foreign key property to other entities, in the joining entity. Step 2 – Add collection navigation property on the other entities towards the joining entity. Step 3 – Next create DB Context OnModelCreating() method configure both the foreign keys in the joining entity as a composite key using Fluent API.
Step 1 − First, create the console application from File → New → Project… Step 2 − Select Windows from the left pane and Console Application from the template pane. Step 3 − Enter EFCodeFirstDemo as the name and select OK. Step 4 − Right-click on your project in the solution explorer and select Manage NuGet Packages…
This is not really solvable by only setting entity states. You must load the customer from the database first including all its current types and then remove types from or add types to the loaded customer according to the updated types collection of the posted customer. Change tracking will do the rest to delete entries from the join table or insert new entries:
public void Put([FromBody]CustomerModel customer)
{
using (var context = new MyContext())
{
var customerInDb = context.Customers.Include(c => c.CustomerTypes)
.Single(c => c.Id == customer.Id);
// Updates the Name property
context.Entry(customerInDb).CurrentValues.SetValues(customer);
// Remove types
foreach (var typeInDb in customerInDb.CustomerTypes.ToList())
if (!customer.CustomerTypes.Any(t => t.Id == typeInDb.Id))
customerInDb.CustomerTypes.Remove(typeInDb);
// Add new types
foreach (var type in customer.CustomerTypes)
if (!customerInDb.CustomerTypes.Any(t => t.Id == type.Id))
{
context.CustomerTypes.Attach(type);
customerInDb.CustomerTypes.Add(type);
}
context.SaveChanges();
}
}
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