c# - Entity Framework Many-to-Many update without creating duplicates? -
i using entity framework (code-first) create database, part of contains 2 entities many-to-many relationship. here code:
public class product { [key] public int productid { get; set; } [maxlength(50)] public string cusip { get; set; } [maxlength(50)] public string sedol { get; set; } [maxlength(50)] public string buid { get; set; } [maxlength(50)] public string key { get; set; } [required] public bool track { get; set; } [inverseproperty("products")] [foreignkey("productlistid")] public virtual list<productlist> productlists { get; set; } public override string tostring() { return string.format("product[ productid: {0}, cusip: {1}, sedol: {2}, buid: {3}, key: {4}, track: {5}, productlists: {6} ]", productid, cusip, sedol, buid, key, track, (productlists != null ? ""+productlists.count : "null")); } } public class productlist { [key] public int productlistid { get; set; } [required] [maxlength(50)] public string name { get; set; } [inverseproperty("productlists")] [foreignkey("productid")] public virtual list<product> products { get; set; } public override string tostring() { return string.format("product-list[ productlistid: {0}, name: {1}, products: {2} ]", productlistid, name, (products != null ? "" + products.count : "null")); } }
in repository, attempting write update method product, such changing tracking boolean or adding/removing productlist save database. using angularjs , asp.net-mvc rest of project, here update method in productscontroller class:
public void put(int id, [frombody] product product) { _repo.updateproduct(id, product); _repo.save(); }
because called angularjs, product object initialized js object.
and finally, here's updateproduct
method in repository:
public bool updateproduct(int id, models.product product) { if (product != null) system.diagnostics.debug.writeline("updateproduct() [" + id + "]\n" + product.tostring()); if (id == 0) return addproduct(product); try { product ctxproduct = getproduct(id); if (ctxproduct != null && product != null) { ctxproduct.cusip = product.cusip; ctxproduct.sedol = product.sedol; ctxproduct.buid = product.buid; ctxproduct.key = product.key; ctxproduct.track = product.track; /*ctxproduct.productlists = new list<productlist>(); (int = 0; < product.productlists.count; i++) { ctxproduct.productlists.add((product.productlists[i].productlistid == 0) ? product.productlists[i] : getproductlistincludingproducts(product.productlists[i].productlistid)); }*/ return true; } return false; } catch (exception e) { system.diagnostics.debug.writeline(e.message + "\n ----- " + e.innerexception); return false; } }
right now, section should update productlist relations commented out. while it's this, can update other field in product , work expected.
if uncomment section, code create duplicate productlists in database, duplicates of products contained in lists.
lastly, if replace getproductlistincludingproducts(product.productlists[i].productlistid)
getproductlist(product.productlists[i].productlistid)
, following error _repo.save()
:
system.data.sqlclient.sqlexception: violation of primary key constraint 'pk_dbo.productlistproducts'. cannot insert duplicate key in object 'dbo.productlistproducts'
getproductlistincludingproducts() adds .include("products") in call context.
i update method readjust many many relationship without crashing or creating lot of duplicate data.
it took awhile figured out. turns out problem webapi formatter. code defaulting xmlmediaformatter - when expecting using jsonmediaformatter set handle reference tracking. in case helps anybody, here final updateproduct method works jsonmediaformatter:
public bool updateproduct(int id, product product) { if (product != null) system.diagnostics.debug.writeline("updateproduct() [" + id + "] " + product.tostring()); if (id == 0) return addproduct(product); try { product ctxproduct = getproductincludingproductlists(id); if (ctxproduct != null && product != null) { ctxproduct.cusip = product.cusip; ctxproduct.sedol = product.sedol; ctxproduct.buid = product.buid; ctxproduct.key = product.key; ctxproduct.track = product.track; ctxproduct.productlists = new list<productlist>(); foreach (productlist pl in product.productlists) ctxproduct.productlists.add(pl.productlistid == 0 ? pl : getproductlist(pl.productlistid)); return true; } return false; } catch (exception e) { system.diagnostics.debug.writeline("update product error: " + e.message + "\ninner: " + e.innerexception); return false; } }
Comments
Post a Comment