首页 文章

实体Famework核心 - 无法跟踪实体类型的实例,因为已经跟踪了具有相同密钥的此类型的另一个实例

提问于
浏览
0

我目前正在尝试使用.net核心和EF核心 .

我有以下代码来更新数据

protected void Update(T entity, bool saveChanges = true)
{
    _context.Set<T>().Attach(entity);
    _context.Entry(entity).State = EntityState.Modified;
    if (saveChanges) _context.SaveChanges();
}

我正在更新的课程

public partial class Blog
{
    public Blog()
    {
        Post = new HashSet<Post>();
    }

    public int BlogId { get; set; }
    public string Url { get; set; }

    public virtual ICollection<Post> Post { get; set; }
}

当我第一次尝试更新任何条目时,它是成功的 . 我第二次更新相同的条目,我得到以下错误:

System.InvalidOperationException:'无法跟踪实体类型'Blog'的实例,因为已经跟踪了具有相同键的此类型的另一个实例 . 添加新实体时,对于大多数密钥类型,如果未设置密钥,则将创建唯一的临时密钥值(即,如果为密钥属性指定了其类型的默认值) . 如果要为新实体显式设置键值,请确保它们不会与现有实体或为其他新实体生成的临时值发生冲突 . 附加现有实体时,请确保只有一个具有给定键值的实体实例附加到上下文 .

每个条目都会出现相同的情况,第一次成功,第二次失败 .

附加信息:我使用以下代码获取所有数据:

protected IEnumerable<T> GetAll()
{
    return _context.Set<T>().AsNoTracking().AsEnumerable();
}

在视图中将上面显示为表格 . DTO用于在数据和Web层之间进行通信 .

上下文在启动时注册如下

services.AddDbContext<BloggingContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

我的问题是为什么在第二次更新期间出现错误以及如何解决它 . 谢谢 .

1 回答

  • 0

    您的服务提供商是静态的,因此它实际上是一个单身人士 . 正如这里建议github.com/aspnet/EntityFramework/issues/2652

    该异常意味着您尝试将具有相同键的两个实体实例附加到上下文 . 在启动时注入存储库的单例实例时会发生这种情况 .

    我建议将通用存储库从抽象类更改为接口,并在启动期间注入正确的存储库:

    services.AddScoped<IRepository<Blog>, BlogRepository>();
    services.AddScoped<IRepository<Post>, PostRepository>();
    

    而不是静态的ServiceProvider,它实际上提供了BlogRepository的单例实现

相关问题