我使用VisualStudio 2017与.Net Core 2和EntityFrameworkCore(v2.0.1)。该应用程序是一个控制台应用程序,它启动MQTT客户端,然后处理收到的消息,并将它们存储到数据库中。
每次应用程序启动时,第一次更新都会按预期工作。但是,在每次使用相同数据的后续更新(无,一个或多个字段已更改)时,它会抛出System.InvalidOperationException,并显示以下消息:
实体类型的实例' Entity1'无法跟踪,因为 另一个具有键值' [SomeKeyValue]'已经存在了 跟踪。附加现有实体时,请确保只有一个实体 附加了具有给定键值的实例。
实体非常简单,只使用一对多关系。
我也在WebApi中使用相同的存储库写入同一个数据库,这里相同的更新代码按预期工作而没有错误。我将控制台应用程序连接起来使用WebApi,这样就行了,即使它与存储库和数据库完全相同。
我尝试了我在互联网上找到的各种建议,例如明确分离实体,但没有一个有效。
使用依赖注入
,设置与Asp.Net WebApi的设置相同services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString));
一对多关系配置如下:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Entity1>()
.HasOne<Entity2>(di => di.Entity1)
.WithMany(d => d.Entity2)
.HasForeignKey(d => d.Entity1Id);
}
实体是:
public class Entity1: ClientChangeTracker
{
[Key]
public string Id{ get; set; }
public ICollection<Entity2> Entity2{ get; set; }
...
}
public class Entity2: ClientChangeTracker
{
[Key]
public string Id{ get; set; }
public Entity1 Entity1{get; set; }
public string Entity1Id{ get; set; }
...
}
添加实体的存储库代码:
public void AddEntity(Entity1 entity1)
{
if (_context.Entity1s.Any(x => x.Id== entity1.Id))
{
_context.Entity1s.Update(entity1).Entity;
}
else
{
_context.Entity1s.Add(entity1).Entity;
}
_context.SaveChanges();
}
任何人都知道为什么会发生这种情况以及如何解决这个问题?
答案 0 :(得分:1)
似乎在IoC容器中配置DbContext需要在控制台应用程序内部执行额外步骤。而不是
services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString));
它需要一个附加参数来将ServiceLifetime指定为Transient:
services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString), ServiceLifetime.Transient);
这似乎解决了这个问题。