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

时间:2017-04-21 09:36:15

标签: c# entity-framework asp.net-core-mvc entity-framework-core

我目前正在尝试使用.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:&#39;实体类型的实例&#39; Blog&#39;无法跟踪,因为已经跟踪了具有相同密钥的此类型的另一个实例。添加新实体时,对于大多数密钥类型,如果未设置密钥,则将创建唯一的临时密钥值(即,如果为密钥属性指定了其类型的默认值)。如果要为新实体显式设置键值,请确保它们不会与现有实体或为其他新实体生成的临时值发生冲突。附加现有实体时,请确保只有一个具有给定键值的实体实例附加到上下文。&#39;

每个条目都是如此,第一次成功,第二次失败。

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

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

在视图中将上面显示为表格。 DTO正被用于在数据和网络层之间进行通信。

上下文在启动时注册如下

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

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

1 个答案:

答案 0 :(得分:0)

您的服务提供商是静态的,因此它实际上是一个单身人士。 如此处所示 github.com/aspnet/EntityFramework/issues/2652

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

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

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

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