之所以会有这个异常,八成是因为之前在同一个DbContext下已经将这个对象Attach到了Context里,即已经搜索过
而现在要操作的对象八成是new或clone出来的对象,拥有相同的主键值,但不是同一个对象实例。
要解决只有一个思路,就是当这个异常发生时,找到Context里那个同主键值的对象,然后强行更改这个对象的值为你要操作的那个,这样就行了。
所以代码如下,先找到那个同主键值的对象:
public T GetEntityKeyNames<T>(DbContext context,T obj) where T:class { if (context == null) { throw new ArgumentNullException("context"); } var set = ((IObjectContextAdapter)context).ObjectContext.CreateObjectSet<T>(); var entitySet = set.EntitySet; string[] keyNames = entitySet.ElementType.KeyMembers.Select(k => k.Name).ToArray(); string precidate = string.Empty; foreach(string filter in keyNames) { precidate+= "it."+filter+"="+context.Entry<T>(obj).Property(filter).CurrentValue.ToString(); } return set.Where(precidate).First(); }
真正的状态改变则可以调用如下代码:
public void Update<T>(T obj) where T : class { using (BE50Beta_AdminEntities1 context = new BE50Beta_AdminEntities1()) { try { context.Entry<T>(obj); } catch { //context.ChangeTracker.Entries<Patron>().ToList().Remove(GetEntityKeyNames(context, pE); context.Entry<T>(GetEntityKeyNames(context, obj)).CurrentValues.SetValues(obj); } } }
这样每次SaveChange就不用担心对象是不是已经被加载到Context中了