The instance of entity type 'Book' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
上面这个错误把我折磨透了,没办法只能把Update的方法仔细研究了一遍。
原因:
DbContext 实例会自动跟踪从数据库返回的实体。 调用 SaveChanges 时,系统将检测对这些实体所做的更改并根据需要更新数据库。有时会使用一个上下文实例查询实体,然后使用实例对其进行保存,或者使用其他实例对实体进行保存。两种情况的做法不一样,需要区别对待。
情况一:共用一个DbContex对实体查询与保存
由于DbContex已经存在一个实体,只需要更新实体数据就可以。如果不存在就插入。
public static void InsertOrUpdate(BloggingContext context, Blog blog) { var existingBlog = context.Blogs.Find(blog.BlogId); if (existingBlog == null) { context.Add(blog); } else { context.Entry(existingBlog).CurrentValues.SetValues(blog); } context.SaveChanges(); }
情况二:不同DbContext对实体进行查询与保存
由于DbContex不存在实体,这个实体是否在数据库中存在我们需要判断才行。
常见 Web 应用程序,属于这种情况。实体被查询、发送到客户端、被修改、在请求中发送回服务器,然后进行保存。
public static void InsertOrUpdate(DbContext context, object entity) { context.Update(entity); context.SaveChanges(); }
EF Core 2.0之后,Update 方法通常将实体标记为更新。 但是,如果实体具有自动生成的键且未设置任何键值,则实体会自动标记为插入。