我很难在InsertOrUpdate上实现一个非常基本的“DbContext ()”方法。我试着遵循this post中的建议。
private static bool SaveItem<TEntity>(Object objToSave, TEntity existing = null) where TEntity : class
{
try
{
/////////////////////////////////////////
// BLOCK A
if(existing != null)
db.Set<TEntity>().Attach(existing);
/////////////////////////////////////////
db.Entry(objToSave).State = existing!=null ? EntityState.Modified : EntityState.Added;
db.SaveChanges();
} catch(Exception e)
{
Logger.Exception(e);
return false;
}
return true;
}下面是一个示例调用:
SaveItem(item, db.MyInstances.Where(dbItem => dbItem.ID == item.ID).FirstOrDefault());一些定义:
class MyInstancesDbContext: DbContext { ... }
private static MyInstancesDbContext db = new MyInstancesDbContext();据我所知,在那个调用中,.Where()将导致某种类型的附件。因此,我尝试了两种方法,包括标记为"A“的小代码块,并将其删除。这两件事给了我同样的错误:
System.InvalidOperationException:附加'...MyInstance‘类型的实体失败,因为相同类型的另一个实体已经具有相同的主键值。这可能发生在使用“附加”方法或将实体的状态设置为“未更改”或“修改”时,如果图形中的任何单位有相互冲突的键值。这可能是因为一些实体是新的,还没有收到数据库生成的键值。在本例中,使用'Add‘方法或’Add‘实体状态来跟踪图形,然后根据情况将非新实体的状态设置为“未更改”或“修改”。
我在这个错误上找到了this popular related answer,用户建议使用AsNoTracking(),但这反而让我觉得自己根本不理解什么,或者试图忽略一些错误。
如有任何建议,我将不胜感激。
发布于 2015-06-07 05:51:27
我认为您缺少的是DbContext跟踪实体,它不喜欢使用相同的主键跟踪相同类型的实体。
如果数据库中存在主键== item.ID,则将其加载到上下文中。
existing已经被附加了--但是这可能不会导致错误。
if(现有!= null) db.Set().Attach(现有);如果是existing == null,您可能不会介意,因为这一行将附加objToSave,但如果存在existing,则会遇到问题,因为您将尝试附加与existing具有相同类型和主键的objToSave。
相反,您可以尝试使用objToSave设置附加实体的值:
db.Entry(existing).CurrentValues.SetValues(objToSave);因此,如果存在现有记录,则不会附加objToSave。
https://stackoverflow.com/questions/30686487
复制相似问题