I have an app that uses the entity framework. I have 2 DB contexts, one for the live sql database and another using InMemory for users to demo the site without changing the live db. The problem is when I add new entries to a table, the 2nd time I try I get this error.
InvalidOperationException: The instance of entity type 'ApplicationUser' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
I’m configuring the DB contexts like this
services.AddDbContextPool<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
var databaseName = new Guid().ToString();
services.AddDbContext<DemoDbContext>(options =>
options.UseInMemoryDatabase(databaseName), ServiceLifetime.Scoped);
services.AddIdentity<ApplicationUser, IdentityRole>(config =>
{
config.Password.RequiredLength = 6;
config.Password.RequireDigit = false;
config.Password.RequireUppercase = false;
config.Password.RequireNonAlphanumeric = false;
config.User.RequireUniqueEmail = true;
})
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<AppDbContext>();
I’m also using AsNoTracking when getting data for the demo user
public IEnumerable<Ticket> GetTicketsForUserRole(ApplicationUser user)
{
return _demoDbContext.Ticket.AsNoTracking()
.Include(ticket => ticket.Author)
.Include(ticket => ticket.Priority)
.Include(ticket => ticket.State)
.Include(ticket => ticket.Project)
.Include(ticket => ticket.Type)
.Include(ticket => ticket.AssignedUser)
.Include(ticket => ticket.Comments)
.ThenInclude(c => c.User)
.Include(ticket => ticket.Attachments)
.ThenInclude(a => a.User);
}
I don’t get the error when using the normal login and appDbContext.
This is where the issue occurs
[HttpPost]
public async Task<IActionResult> AddComment(TicketsViewModel viewModel)
{
if(viewModel.TicketId != null)
{
var applicationUser = await _userManager.GetUserAsync(User);
var roleObject = _roleFactory.GetRole(applicationUser);
var ticket = roleObject.GetTicketsForUserRole(applicationUser)
.First(t => t.Id == viewModel.TicketId);
viewModel.Ticket = ticket;
var comment = new Comment
{
Date = DateAndTime.Now,
TextComment = viewModel.TextComment,
User = applicationUser
};
ticket.Comments.Add(comment);
roleObject.UpdateTicket(ticket);
return RedirectToAction("Details", new { id = viewModel.Ticket.Id });
}
return NoContent();
}
When I add the first comment it’s ok, then I get the error when adding a second.
I am updating the ticket correctly?
public void UpdateTicket(Ticket ticket)
{
_demoDbContext.Ticket.Update(ticket);
_demoDbContext.SaveChanges();
}