c# - Updating object with child collection using Entity Framework causing duplicates in database -
i have customer
class has relationship address
class:
public class customer { public int id { get; set; } public string name { get; set; } public virtual icollection<address> addresses { get; set; } } public class address { public int id { get; set; } public string street1 { get; set; } //snip bunch of properties public virtual customer customer { get; set; } }
i have edit form displays fields both customer , address. when form submitted, calls edit
method in controller:
public actionresult save(customer customer) { if (!modelstate.isvalid) { var viewmodel = new customerformviewmodel { customer = customer, customertypes = _context.customertypes.tolist() }; return view("customerform", viewmodel); } if (customer.id == 0) _context.customers.add(customer); else { var existingcustomer = _context.customers .include(c => c.addresses) .single(c => c.id == customer.id); existingcustomer.name = customer.name; existingcustomer.taxid = customer.taxid; existingcustomer.customertypeid = customer.customertypeid; existingcustomer.creditlimit = customer.creditlimit; existingcustomer.exempt = customer.exempt; existingcustomer.addresses = customer.addresses; } _context.savechanges(); return redirecttoaction("index", "customers"); }
this doesn't work , creates duplicate entries in addresses
table in db. think understand why (ef isn't smart enough know addresses inside collection need added/modified/deleted case may be). so, best way fix this?
my instinct need iterate on addresses
collections , compare them manually, adding new ones form don't exist customer, updating ones exist, , deleting ones not sent form exist in db customer. (ignoring delete functionality now):
foreach(address address in customer.addresses) { if (address.id == 0) // add record else // fetch address record db // update data } // save context
is best way go this, or there ef tricks iterating , syncing child collection db?
oh, , 1 question has me scratching head - can sort of understand how new address record getting created in db, don't existing address record updated have customer_id
set null...how heck happen? leads me believe ef see original address record somehow linked (as modifying it) it's not smart enough realize record i'm passing in should replace it?
thanks -- also, ef6 , mvc5
the problem comes line
existingcustomer.addresses = customer.addresses;
in code. assigns field addresses
customer
coming model. far ok. point customer
not have relation database model @ point (it's not coming database view).
if update existingcustomer.addresses
data coming model, need merge data instead of replacing it. following "pseudo code" might give direction:
void mergeaddresses(var existingaddresses, var newaddresses) { foreach(var address in newaddresses) { if (existingaddresses.contains(newaddress)) { // merge fields if applicable } else { // add field existingaddresses - ware use "cloned" list } } // delete items existing list foreach (var address in existingaddresses.clonelist()) { if (!newaddresses.contains(address)) { // remove existingaddresses } } }
Comments
Post a Comment