c# - issue attaching/adding an entity object which is detached from the DB Context? -
i new ef , seem have become bit stuck following issue..
i have following situation.
two applications using same database, , have both loaded context @ same time displaying same information.
application 1 goes , deletes entity , updates database savechanges. application 2 goes , saves same modified entity.
we using updategraph recurse through tree , save entities database context. however, when come saving deleted entity, doesn't exist in db context obtained database want add database.
i have tried doing add, gives multiplicity error trying add full tree context!
any ideas please?
the following code snippet updategraph extension method. (http://github.com/refactorthis/graphdiff)
private static void recursivegraphupdate<t>(dbcontext context, t datastoreentity, t updatingentity, updatemember member) t:class { if (member.iscollection) { // dealing collection var updatevalues = (ienumerable)member.accessor.getvalue(updatingentity, null); var dbcollection = (ienumerable)member.accessor.getvalue(datastoreentity, null); var keyfields = context.getkeysfor(updatevalues.gettype().getgenericarguments()[0]); var dbhash = mapcollectiontodictionary(keyfields, dbcollection); // iterate through elements updated graph , try match them against db graph. list<object> additions = new list<object>(); foreach (object updateitem in updatevalues) { var key = createhash(keyfields, updateitem); // try find in db collection object dbitem; var itemid = updateitem.gettype().getproperty("id"); if (dbhash.trygetvalue(key, out dbitem)) { var property = updateitem.gettype().getproperty("deleted"); bool ysn = property.getvalue(updateitem, null).tostring() == "true" ? true : false; if (ysn) { context.entry(dbitem).currentvalues.setvalues(updateitem); continue; } // if own collection if (member.isowned) { context.entry(dbitem).currentvalues.setvalues(updateitem); // match means updating foreach (var childmember in member.members) recursivegraphupdate(context, dbhash[key], updateitem, childmember); } dbhash.remove(key); // remove leave db removals in collection } else additions.add(updateitem); } // removal of dbitem's left in collection foreach (var dbitem in dbhash.values) { var property = dbitem.gettype().getproperty("deleted"); bool ysn = property.getvalue(dbitem, null).tostring() == "true" ? true : false; if (ysn) { // own collection remove completely. if (member.isowned) context.set(dbitem.gettype()).remove(dbitem); dbcollection.gettype().getmethod("remove").invoke(dbcollection, new[] { dbitem }); } } // add elements marked addition foreach (object newitem in additions) { if (!member.isowned) context.set(newitem.gettype()).attach(newitem); // otherwise add object dbcollection.gettype().getmethod("add").invoke(dbcollection, new[] { newitem }); } } else // not collection { var dbvalue = member.accessor.getvalue(datastoreentity, null); var newvalue = member.accessor.getvalue(updatingentity, null); if (dbvalue == null && newvalue == null) // no value return; // if own collection need update entities otherwise simple relationship update if (!member.isowned) { if (dbvalue != null && newvalue != null) { var keyfields = context.getkeysfor(newvalue.gettype()); var newkey = createhash(keyfields, newvalue); var updatekey = createhash(keyfields, dbvalue); if (newkey == updatekey) return; // nothing if same key } if (context.entry(newvalue).state == entitystate.detached) context.set(newvalue.gettype()).attach(newvalue); member.accessor.setvalue(datastoreentity, newvalue, null); context.entry(newvalue).reload(); // todo this: context.entry(newvalue).state = entitystate.unchanged; // seems though in unchanged state ef still update database if original values different. } else { if (dbvalue != null && newvalue != null) { // check if same key, if update values on entity var keyfields = context.getkeysfor(newvalue.gettype()); var newkey = createhash(keyfields, newvalue); var updatekey = createhash(keyfields, dbvalue); // perform update if same if (updatekey == newkey) { context.entry(dbvalue).currentvalues.setvalues(newvalue); context.entry(dbvalue).state = entitystate.modified; } else member.accessor.setvalue(datastoreentity, newvalue, null); } else member.accessor.setvalue(datastoreentity, newvalue, null); // todo foreach (var childmember in member.members) recursivegraphupdate(context, dbvalue, newvalue, childmember); } } }
Comments
Post a Comment