【问题标题】:Deleting recording using a stub object使用存根对象删除记录
【发布时间】:2019-05-15 01:37:14
【问题描述】:

我已经看到并且我确信在 EF Core 中使用了这种技术,通过创建存根对象来删除记录以保存到数据库的行程,但是使用这种方法不会向数据库发送删除。有谁知道为什么?

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”来查看冲突的键值。

【问题讨论】:

  • 您不需要在条目上设置State。调用 _context.Remove(blogPost) 会将实体添加到跟踪更改机制并将其(和相关实体)状态设置为已删除。
  • 根据您的第一个示例不工作,这很奇怪,因为它应该工作。这是你的真实代码,还是只是它的简化?
  • 这是完整的代码,因为它是一个演示问题的测试。如果我没有将状态设置为已删除,则会收到我在帖子中更新的错误。

标签: entity-framework-core


【解决方案1】:

此回答来自HERE

如果您确定数据库中存在所有 Id 并且上下文不包含(不跟踪)具有相同键的其他实体,则可以使用简单的假(存根)实体:

_context.RemoveRange(ids.Select(id => new File { Id = id }));

为避免跟踪实体问题,您可以使用我对Delete loaded and unloaded objects by ID in EntityFrameworkCore 的回答中的 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 }));

【讨论】:

  • 这是另一个问题的答案。
  • Tig2810 不,这是准确的答案。他想在没有跟踪模型的情况下使用 EF Core 删除,而只有 ID,也就是 Stub 模型。
  • 这正是我所做的,但它不起作用——另一篇文章是关于收藏的。在 docs.microsoft 中,他们的示例是使用 EntityState.Deleted,而不是删除,但这对 SaveChanges 具有相同的效果,即不发送删除。
猜你喜欢
  • 1970-01-01
  • 2020-11-12
  • 1970-01-01
  • 1970-01-01
  • 2019-07-15
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多