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

Popular posts from this blog

asynchronous - C# WinSCP .NET assembly: How to upload multiple files asynchronously -

aws api gateway - SerializationException in posting new Records via Dynamodb Proxy Service in API -

asp.net - Problems sending emails from forum -