JohnCambell
JohnCambell

Reputation: 633

Repeated Update causes tracking error

Im using VisualStudio 2017 with .Net Core 2 and EntityFrameworkCore (v2.0.1). The application is a console application which starts an MQTT Client and then processes the received messages, storing them into a database.

Each time the application starts and on the first update it works as expected. However on each subsequent update with the same data (none, one or more fields are changed), it throws an System.InvalidOperationException with the following message:

The instance of entity type 'Entity1' cannot be tracked because another instance with the key value '[SomeKeyValue]' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.

The entities are fairly simple, only using a One-To-Many relationship.

I also have the same repository used in a WebApi writing to the same database, and here the same update code works as expected without errors. I hooked up the Console App to use the WebApi instead, and this works, even though it is exactly the same Repository and Database.

I tried various recommendations I found on the internet, which is for example to explicitly detach the entity, but none of that worked.

The setup is the same as for the Asp.Net WebApi, using dependency injection

services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString));

The One-To-Many Relations is configured like this:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity<Entity1>()
  .HasOne<Entity2>(di => di.Entity1)
  .WithMany(d => d.Entity2)
  .HasForeignKey(d => d.Entity1Id);              
 }

The Entities are:

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; }
  ...
}

The repository code for adding entity:

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();
}

Anybody any idea why this is happening and how it can be fixed?

Upvotes: 2

Views: 1826

Answers (1)

JohnCambell
JohnCambell

Reputation: 633

It appears that configuring DbContext in the IoC container requires an extra step inside of a Console Application. Instead of

services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString));

it requires an addition parameter to specify the ServiceLifetime as Transient:

services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString), ServiceLifetime.Transient);

This seems to fix the problem.

Upvotes: 2

Related Questions