我已经看到了,并且我确信可以通过创建存根对象来保存到db的行程,将该技术与EF Core一起使用来删除记录,但是使用此方法永远不会将删除发送到db。有人知道为什么吗?
public void DeleteById(int blogPostId)
{
// Does not work
// Use Stub to save extra db trip
/*
var blogPost = new BlogPost { Id = blogPostId };
_context.Entry(blogPost).State = EntityState.Deleted;
_context.BlogPosts.Remove(blogPost);
_context.SaveChanges();
*/
// Works
var blogPost = _context.BlogPosts.Find(blogPostId);
_context.Entry(blogPost).State = EntityState.Deleted;
_context.BlogPosts.Remove(blogPost);
_context.SaveChanges();
}
还有一个问题,直接在上下文或DbSet上使用remove都是有区别的吗?
_context.Remove(blogPost);
_context.BlogPosts.Remove(blogPost);
如果我将代码更改为以下内容:
public void DeleteById(int blogPostId)
{
// Does not work
// Use Stub to save extra db trip
var blogPost = new BlogPost { Id = blogPostId };
//_context.Entry(blogPost).State = EntityState.Deleted;
_context.BlogPosts.Remove(blogPost);
_context.SaveChanges();
// Works
//var blogPost = _context.BlogPosts.Find(blogPostId);
//_context.Entry(blogPost).State = EntityState.Deleted;
//_context.BlogPosts.Remove(blogPost);
//_context.SaveChanges();
}
我收到以下错误:
An unhandled exception has occurred while executing the request.
System.InvalidOperationException:无法跟踪实体类型'BlogPost'的实例,因为已经跟踪了另一个具有相同'{'Id'}键值的实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。考虑使用'DbContextOptionsBuilder.EnableSensitiveDataLogging'查看冲突的键值。
答案 0 :(得分:0)
此答案来自https://launchpad.net/ubuntu/trusty/armhf/chromium-chromedriver/65.0.3325.181-0ubuntu0.14.04.1
如果您确定数据库中存在所有ID,并且上下文不包含(不跟踪)具有相同密钥的其他实体,则可以使用简单的假(存根)实体:
_context.RemoveRange(ids.Select(id => new File { Id = id }));
为避免跟踪实体问题,您可以从我对HERE的回答中使用FindTracked自定义扩展方法,并将其与以上任何方法结合使用。
var existingIds = _context.Files.Where(f => ids.Contains(f.Id)).Select(f => f.Id).ToList();
_context.RemoveRange(
existingIds.Select(id => _context.FindTracked(id) ?? new File { Id = id }));